diff --git a/gates/pool.py b/gates/pool.py index 1020bd2..a5865a1 100644 --- a/gates/pool.py +++ b/gates/pool.py @@ -44,6 +44,23 @@ def write_manifest(base_dir, pool_id, manifest): return manifest +def next_image_name(manifest): + return f"img_{manifest.get('next_seq', 1):04d}.png" + + +def add_image(base_dir, pool_id, data, ts=0): + m = read_manifest(base_dir, pool_id) + name = next_image_name(m) + d = pool_dir(base_dir, pool_id) + d.mkdir(parents=True, exist_ok=True) + with open(d / name, "wb") as f: + f.write(data) + m["slots"].append({"image": name, "mask": None, "label": "", "added": ts}) + m["next_seq"] = m.get("next_seq", 1) + 1 + write_manifest(base_dir, pool_id, m) + return m + + def rebuild_manifest(base_dir, pool_id): # Temporary stub — replaced in Task 7. return empty_manifest() diff --git a/tests/test_pool.py b/tests/test_pool.py index 44fa6e0..8666d2c 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -26,3 +26,26 @@ def test_write_is_atomic_no_partial_temp_left(tmp_path): pool.write_manifest(str(tmp_path), "p1", pool.empty_manifest()) leftovers = list((tmp_path / "p1").glob("*.tmp")) assert leftovers == [] + + +def test_next_image_name_uses_next_seq(): + m = pool.empty_manifest() + assert pool.next_image_name(m) == "img_0001.png" + m["next_seq"] = 42 + assert pool.next_image_name(m) == "img_0042.png" + + +def test_add_image_writes_file_and_appends_slot(tmp_path): + data = b"\x89PNG\r\n\x1a\n" + b"fake" # bytes are written verbatim + m = pool.add_image(str(tmp_path), "p1", data, ts=123) + assert len(m["slots"]) == 1 + slot = m["slots"][0] + assert slot == {"image": "img_0001.png", "mask": None, "label": "", "added": 123} + assert m["next_seq"] == 2 + assert (tmp_path / "p1" / "img_0001.png").read_bytes() == data + + +def test_add_image_monotonic_after_growth(tmp_path): + pool.add_image(str(tmp_path), "p1", b"a", ts=1) + m = pool.add_image(str(tmp_path), "p1", b"b", ts=2) + assert [s["image"] for s in m["slots"]] == ["img_0001.png", "img_0002.png"]