From 2b1c1ab3b0374496b9c666eff185c41a50723b46 Mon Sep 17 00:00:00 2001 From: "Peter B. Johnson" Date: Fri, 30 Oct 2026 09:47:30 +0000 Subject: [PATCH] Record that the import relies on the zip's question order Lambda Feedback imports questions in archive order until the platform takes question order explicitly. Say so where the zip is sorted and beside the zero-padded filename prefix, note it in the fixtures README, and test that the zip lists questions in orderNumber order. Co-Authored-By: Claude Opus 5.5 --- in2lambda/json_convert/json_convert.py | 3 +++ tests/fixtures/exports/README.md | 2 +- tests/test_export_keys.py | 11 +++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/in2lambda/json_convert/json_convert.py b/in2lambda/json_convert/json_convert.py index 270ef38..aa9548f 100644 --- a/in2lambda/json_convert/json_convert.py +++ b/in2lambda/json_convert/json_convert.py @@ -15,6 +15,8 @@ def _zip_sorted_folder(folder_path, zip_path): """Zips the contents of a folder, preserving the directory structure. + Lambda Feedback imports questions in archive order, so the files are sorted. + Args: folder_path: The path to the folder to zip. zip_path: The path where the zip file will be created. @@ -187,6 +189,7 @@ def converter(SetQuestions: Set, output_dir: str) -> None: # Output file filename = ( "question_" + # Alphabetical order is question order for up to 1000 questions + str(i).zfill(3) + "_" + re.sub(r"[^\w\-_.]", "_", output["title"].strip()) diff --git a/tests/fixtures/exports/README.md b/tests/fixtures/exports/README.md index b98f2a0..b9a8a7a 100644 --- a/tests/fixtures/exports/README.md +++ b/tests/fixtures/exports/README.md @@ -24,7 +24,7 @@ answers, worked solutions, structured tutorials and the chatbot. | key | meaning | |---|---| -| `orderNumber` | position in the set, from 0; matches the filename | +| `orderNumber` | position in the set, from 0; matches the filename. The importer currently follows archive order, so the two must agree | | `title` | shown to students | | `skill` | difficulty (exports use 1/3 and 2/3) | | `guidance` | a sentence to students about the question's purpose | diff --git a/tests/test_export_keys.py b/tests/test_export_keys.py index eaadb08..ea8b9e6 100644 --- a/tests/test_export_keys.py +++ b/tests/test_export_keys.py @@ -7,6 +7,7 @@ """ import json +import zipfile from pathlib import Path from in2lambda.api.part import Part @@ -93,3 +94,13 @@ def test_each_response_type_writes_the_settings_of_a_real_export() -> None: evaluation_function="" ) assert set(written._config() or {}) == set(response["config"] or {}) + + +def test_the_zip_lists_questions_in_order_number_order(tmp_path) -> None: + titles = ["Zeta", "Alpha", "Mu"] + Set(questions=[Question(title=t) for t in titles]).to_json(str(tmp_path)) + + with zipfile.ZipFile(tmp_path / "set.zip") as zf: + names = [n for n in zf.namelist() if n.startswith("question_")] + orders = [json.loads(zf.read(n))["orderNumber"] for n in names] + assert orders == list(range(len(titles)))