Improve web finalisation navigation, caching and Anot support

This commit is contained in:
sebastien committed 2026-11-03 11:38:39 +01:00
1 parent 5de70dbc0d
commit b069805988
21 files changed
+339 -58

No files matched your search

+93 -1
View File
@@ -212,6 +212,14 @@ class WebTests(unittest.TestCase):
self.service._regenerate(False)
self.assertEqual(calls, ['regenerate-reviewed', 'giving-names'])
def test_exported_final_score_is_bound_to_copy_id_after_rename(self):
self.assertIsNone(self.client.get('/api/state').json()['copies'][0]['finalScore'])
atomic_write_json(self.root/'.copienator/final_scores.json',
{'version':1,'copies':{'1':{'name':'Old name','score':'12.3'}}})
self.assertEqual(self.client.get('/api/state').json()['copies'][0]['finalScore'], '12.3')
self.save('name', 'New name')
self.assertEqual(self.client.get('/api/state').json()['copies'][0]['finalScore'], '12.3')
def test_os_lock_blocks_cli_and_releases(self):
with EvaluationLock(self.root):
with self.assertRaises(CliError):
@@ -277,7 +285,7 @@ class SnapshotTests(unittest.TestCase):
from copienator.commands import regenerate_reviewed
from copienator.commands import annotating
from copienator.custom_remarks import set_remark
for mode in ('Bnot', 'BGnot'):
for mode in ('Bnot', 'BGnot', 'Anot'):
with self.subTest(mode=mode), tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
seed(root, mode)
@@ -331,6 +339,27 @@ class WebGuiTests(unittest.TestCase):
app.state_store.evaluation = None
self.assertEqual(state(), 'disabled')
def test_anot_generation_enables_button_and_selects_anot(self):
from copienator_gui.app import CopienatorApp
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
seed(root, 'Anot')
app = CopienatorApp(Path.cwd(), False, root)
self.addCleanup(app.destroy)
app._update_controls()
self.assertEqual(str(app.finalisation_web_button.cget('state')), 'normal')
app._open_finalisation_web()
dialog = app.grab_current()
def descendants(widget):
for child in widget.winfo_children():
yield child
yield from descendants(child)
combo = next(w for w in descendants(dialog) if w.winfo_class() == 'TCombobox')
self.assertEqual(combo.get(), 'Anot')
self.assertEqual(tuple(combo.cget('values')), ('Anot',))
dialog.grab_release()
dialog.destroy()
def test_modal_lock_and_return_to_existing_workflow(self):
from copienator_gui.app import CopienatorApp
from copienator.finalisation_server import WebSession
@@ -457,3 +486,66 @@ class IncrementalReviewedTests(unittest.TestCase):
(root/'A Rendre/Bob (02)/info.json').unlink()
run(1)
self.assertTrue((root/'A Rendre/Bob (02)/info.json').is_file())
class CrossProcessCacheTests(unittest.TestCase):
def test_reviewed_cache_survives_worker_restart_and_selects_only_two_score_edits(self):
from copienator.review_snapshot import stage
import shutil
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
seed(root, 'BGnot')
output = root/'BGnot/Copie01'
data = {'Ex 1': {'pdf_path':root/'Copies/Copie01/Ex 1.pdf',
'result':{'score':3,'feedback':[]},'coordinates':[0,0]}}
with staged_files(output) as staging:
stage(output, staging, data, {}, engine='grouped')
for cid in ('02','03','04'):
shutil.copytree(output,root/'BGnot'/f'Copie{cid}')
script = '''
import json, sys
from pathlib import Path
from copienator import EvaluationWorkspace, configuration
from copienator.reviewed_cache import ReviewedReadCache
from string import Template
configuration.LATEX_ANOT_BEFORE = Template(sys.argv[3])
root=Path(sys.argv[1])
directories=sorted((root/'BGnot').glob('Copie*'))
cache=ReviewedReadCache(EvaluationWorkspace(root),'BGnot',directories)
if sys.argv[2]=='remember':
cache.remember([d.name[5:] for d in directories])
print(json.dumps([d.name for d in directories if not cache.unchanged(d.name[5:])]))
'''
def run(action='check', template='Stable ${width_in} template'):
return __import__('json').loads(subprocess.check_output(
[sys.executable,'-c',script,str(root),action,template],text=True))
self.assertEqual(run('remember'), [])
self.assertEqual(run(), [])
set_score(root/'BGnot/Copie01/score.json','Ex 1','1')
set_score(root/'BGnot/Copie03/score.json','Ex 1','2')
self.assertEqual(run(), ['Copie01','Copie03'])
self.assertEqual(run('remember'), [])
self.assertEqual(run(), [])
self.assertEqual(run(template='Changed template'), ['Copie01','Copie02','Copie03','Copie04'])
def test_legacy_reader_cache_template_is_stable_across_workers(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
seed(root)
atomic_write_json(root/'Bnot/Copie01/review_snapshot.json', {})
script = '''
import json, sys
from pathlib import Path
from string import Template
from copienator import EvaluationWorkspace, configuration
from copienator.annotation_read_cache import AnnotationReadCache
configuration.LATEX_ANOT_BEFORE=Template('Stable ${width_in} template')
root=Path(sys.argv[1])
data={'01':{'Ex 1':{'pdf_path':root/'Copies/Copie01/Ex 1.pdf'}}}
cache=AnnotationReadCache(EvaluationWorkspace(root),'Bnot',data)
if sys.argv[2]=='remember': cache.remember(['01'])
print(json.dumps(cache.unchanged('01')))
'''
for action in ('remember','check'):
result=subprocess.check_output([sys.executable,'-c',script,str(root),action],text=True)
self.assertEqual(result.strip(),'true')