From 000e83f25367bd2c1ca9aecca3dad57a0d647548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=98=E9=9B=85=E3=81=AE=E5=92=B8=E9=B1=BC?= <3129538298@qq.com> Date: Wed, 26 Aug 2026 17:56:53 +0800 Subject: [PATCH 1/4] fix: copy_asset reports directory as not a file --- src/shotbible/store.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shotbible/store.py b/src/shotbible/store.py index 80f0d6d..7abd7de 100644 --- a/src/shotbible/store.py +++ b/src/shotbible/store.py @@ -99,6 +99,8 @@ def copy_take_file(root: Path, src: Path, take_id: str) -> str: def copy_asset(root: Path, src: Path, kind: str, bucket: str) -> str: src = src.expanduser().resolve() + if src.is_dir(): + raise StoreError(f"not a file: {src}") if not src.is_file(): raise StoreError(f"file not found: {src}") dest_dir = root / kind / _safe_id(bucket) From 93043bc26ac64e71315f781f88a3f4e5ffd66a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=98=E9=9B=85=E3=81=AE=E5=92=B8=E9=B1=BC?= <3129538298@qq.com> Date: Wed, 26 Aug 2026 17:58:12 +0800 Subject: [PATCH 2/4] test: copy_ref rejects directories --- tests/test_store.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_store.py b/tests/test_store.py index 7230971..46a60bb 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -161,6 +161,14 @@ def test_load_invalid_duration_is_store_error(tmp_path: Path) -> None: load(root) +def test_copy_ref_rejects_directory(tmp_path: Path) -> None: + root = init_project(tmp_path / "refs-dir") + folder = tmp_path / "album" + folder.mkdir() + with pytest.raises(StoreError, match="not a file"): + copy_ref(root, folder, "mei") + + def test_example_campus_night_loads() -> None: root, bible = load(EXAMPLE) assert root == EXAMPLE.resolve() From de8a427b0735a75ee11135f1cc99729e9b42b4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=98=E9=9B=85=E3=81=AE=E5=92=B8=E9=B1=BC?= <3129538298@qq.com> Date: Wed, 26 Aug 2026 17:59:32 +0800 Subject: [PATCH 3/4] test: prompt --all honors --beat/--character and rejects -o FILE --- tests/test_cli.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 5c57da1..c576b76 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -111,6 +111,28 @@ def test_cli_prompt_all_writes_each_scene( assert "classroom" in text.lower() or "desks" in text +def test_cli_prompt_all_rejects_output_file( + sample_project: tuple[Path, Bible], + monkeypatch: pytest.MonkeyPatch, +) -> None: + root, _bible = sample_project + monkeypatch.chdir(root) + assert main(["prompt", "--all", "-o", "one.txt"]) == 2 + assert not (root / "one.txt").exists() + + +def test_cli_prompt_all_applies_beat_and_character( + sample_project: tuple[Path, Bible], + monkeypatch: pytest.MonkeyPatch, +) -> None: + root, _bible = sample_project + monkeypatch.chdir(root) + assert main(["prompt", "--all", "--beat", "独自合上笔记本", "--character", "mei"]) == 0 + text = (root / "takes" / "s01.prompt.txt").read_text(encoding="utf-8") + assert "独自合上笔记本" in text + assert NAME in text or "mei" in text + + def test_cli_check_exit_codes( sample_project: tuple[Path, Bible], monkeypatch: pytest.MonkeyPatch ) -> None: From 0a569f11316b1344443980ef43af5319e69c13f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=98=E9=9B=85=E3=81=AE=E5=92=B8=E9=B1=BC?= <3129538298@qq.com> Date: Wed, 26 Aug 2026 18:02:17 +0800 Subject: [PATCH 4/4] fix: prompt --all honors --beat/--character and rejects -o FILE --- src/shotbible/cli.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/shotbible/cli.py b/src/shotbible/cli.py index a441fc3..df68c54 100644 --- a/src/shotbible/cli.py +++ b/src/shotbible/cli.py @@ -382,11 +382,25 @@ def cmd_take_add(args: argparse.Namespace) -> int: def cmd_prompt(args: argparse.Namespace) -> int: root, bible = _load(args) if args.all_scenes: + if args.output not in (None, ""): + raise StoreError( + "prompt --all writes one file per scene under takes/; " + "do not pass -o FILE (use -o with no path for the default)" + ) if not bible.scenes: raise StoreError("no scenes to compile") + character_id = args.character or "" + if character_id: + require_character(bible, character_id) wrote = 0 for sid in bible.scenes: - text = compile_prompt(bible, sid, kind=args.kind) + text = compile_prompt( + bible, + sid, + beat=args.beat or "", + character_id=character_id, + kind=args.kind, + ) _emit_prompt(root, text, "", f"{sid}.prompt.txt") wrote += 1 print(f"wrote {wrote} prompt file(s)")