refactor: use project-named state file and store prompt/params directly
- State filename now derives from config: cards.bulkgen.yaml produces .cards.bulkgen-state.yaml instead of .bulkgen.state.yaml - Store resolved prompt text and extra params directly in state file instead of hashing them, making state files human-readable - Only file input contents remain hashed (SHA-256) - Thread project_name through builder and CLI - Remove hash_string() and _extra_hash() helpers - Update .gitignore pattern to .*.bulkgen-state.yaml
This commit is contained in:
parent
870023865d
commit
0ecf1f0f9e
7 changed files with 98 additions and 82 deletions
|
|
@ -23,6 +23,8 @@ from bulkgen.state import load_state
|
|||
|
||||
WriteConfig = Callable[[dict[str, object]], ProjectConfig]
|
||||
|
||||
_PROJECT = "project"
|
||||
|
||||
|
||||
_FAKE_TEXT_MODELS = [
|
||||
ModelInfo(
|
||||
|
|
@ -196,7 +198,7 @@ class TestRunBuild:
|
|||
self, project_dir: Path, simple_text_config: ProjectConfig
|
||||
) -> None:
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
result = await run_build(simple_text_config, project_dir)
|
||||
result = await run_build(simple_text_config, project_dir, _PROJECT)
|
||||
|
||||
assert result.built == ["output.txt"]
|
||||
assert result.skipped == []
|
||||
|
|
@ -207,7 +209,7 @@ class TestRunBuild:
|
|||
self, project_dir: Path, multi_target_config: ProjectConfig
|
||||
) -> None:
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
result = await run_build(multi_target_config, project_dir)
|
||||
result = await run_build(multi_target_config, project_dir, _PROJECT)
|
||||
|
||||
assert "summary.md" in result.built
|
||||
assert "final.txt" in result.built
|
||||
|
|
@ -222,10 +224,10 @@ class TestRunBuild:
|
|||
self, project_dir: Path, simple_text_config: ProjectConfig
|
||||
) -> None:
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
result1 = await run_build(simple_text_config, project_dir)
|
||||
result1 = await run_build(simple_text_config, project_dir, _PROJECT)
|
||||
assert result1.built == ["output.txt"]
|
||||
|
||||
result2 = await run_build(simple_text_config, project_dir)
|
||||
result2 = await run_build(simple_text_config, project_dir, _PROJECT)
|
||||
assert result2.skipped == ["output.txt"]
|
||||
assert result2.built == []
|
||||
|
||||
|
|
@ -234,11 +236,11 @@ class TestRunBuild:
|
|||
) -> None:
|
||||
config1 = write_config({"targets": {"out.txt": {"prompt": "version 1"}}})
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
r1 = await run_build(config1, project_dir)
|
||||
r1 = await run_build(config1, project_dir, _PROJECT)
|
||||
assert r1.built == ["out.txt"]
|
||||
|
||||
config2 = write_config({"targets": {"out.txt": {"prompt": "version 2"}}})
|
||||
r2 = await run_build(config2, project_dir)
|
||||
r2 = await run_build(config2, project_dir, _PROJECT)
|
||||
assert r2.built == ["out.txt"]
|
||||
|
||||
async def test_rebuild_after_input_change(
|
||||
|
|
@ -249,11 +251,11 @@ class TestRunBuild:
|
|||
{"targets": {"out.md": {"prompt": "x", "inputs": ["data.txt"]}}}
|
||||
)
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
r1 = await run_build(config, project_dir)
|
||||
r1 = await run_build(config, project_dir, _PROJECT)
|
||||
assert r1.built == ["out.md"]
|
||||
|
||||
_ = (project_dir / "data.txt").write_text("modified")
|
||||
r2 = await run_build(config, project_dir)
|
||||
r2 = await run_build(config, project_dir, _PROJECT)
|
||||
assert r2.built == ["out.md"]
|
||||
|
||||
async def test_selective_build_single_target(
|
||||
|
|
@ -261,7 +263,7 @@ class TestRunBuild:
|
|||
) -> None:
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
result = await run_build(
|
||||
multi_target_config, project_dir, target="summary.md"
|
||||
multi_target_config, project_dir, _PROJECT, target="summary.md"
|
||||
)
|
||||
|
||||
assert "summary.md" in result.built
|
||||
|
|
@ -274,7 +276,7 @@ class TestRunBuild:
|
|||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
with pytest.raises(ValueError, match="Unknown target"):
|
||||
_ = await run_build(
|
||||
simple_text_config, project_dir, target="nonexistent.txt"
|
||||
simple_text_config, project_dir, _PROJECT, target="nonexistent.txt"
|
||||
)
|
||||
|
||||
async def test_failed_target_isolates_independent(
|
||||
|
|
@ -322,7 +324,7 @@ class TestRunBuild:
|
|||
"bulkgen.builder._create_providers",
|
||||
return_value=[routing_provider, FakeImageProvider()],
|
||||
):
|
||||
result = await run_build(config, project_dir)
|
||||
result = await run_build(config, project_dir, _PROJECT)
|
||||
|
||||
assert "fail.txt" in result.failed
|
||||
assert "ok.txt" in result.built
|
||||
|
|
@ -343,7 +345,7 @@ class TestRunBuild:
|
|||
"bulkgen.builder._create_providers",
|
||||
return_value=[FailingTextProvider(), FakeImageProvider()],
|
||||
):
|
||||
result = await run_build(config, project_dir)
|
||||
result = await run_build(config, project_dir, _PROJECT)
|
||||
|
||||
assert "base.txt" in result.failed
|
||||
assert "child.txt" in result.failed
|
||||
|
|
@ -356,7 +358,7 @@ class TestRunBuild:
|
|||
"bulkgen.builder._create_providers",
|
||||
return_value=[],
|
||||
):
|
||||
result = await run_build(simple_text_config, project_dir)
|
||||
result = await run_build(simple_text_config, project_dir, _PROJECT)
|
||||
|
||||
assert "output.txt" in result.failed
|
||||
assert "No provider available" in result.failed["output.txt"]
|
||||
|
|
@ -373,9 +375,9 @@ class TestRunBuild:
|
|||
}
|
||||
)
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
_ = await run_build(config, project_dir)
|
||||
_ = await run_build(config, project_dir, _PROJECT)
|
||||
|
||||
state = load_state(project_dir)
|
||||
state = load_state(project_dir, _PROJECT)
|
||||
assert "a.txt" in state.targets
|
||||
assert "b.txt" in state.targets
|
||||
|
||||
|
|
@ -385,7 +387,7 @@ class TestRunBuild:
|
|||
config = write_config({"targets": {"out.txt": {"prompt": prompt_file.name}}})
|
||||
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
result = await run_build(config, project_dir)
|
||||
result = await run_build(config, project_dir, _PROJECT)
|
||||
|
||||
assert result.built == ["out.txt"]
|
||||
content = (project_dir / "out.txt").read_text()
|
||||
|
|
@ -395,12 +397,12 @@ class TestRunBuild:
|
|||
self, project_dir: Path, simple_text_config: ProjectConfig
|
||||
) -> None:
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
r1 = await run_build(simple_text_config, project_dir)
|
||||
r1 = await run_build(simple_text_config, project_dir, _PROJECT)
|
||||
assert r1.built == ["output.txt"]
|
||||
|
||||
(project_dir / "output.txt").unlink()
|
||||
|
||||
r2 = await run_build(simple_text_config, project_dir)
|
||||
r2 = await run_build(simple_text_config, project_dir, _PROJECT)
|
||||
assert r2.built == ["output.txt"]
|
||||
|
||||
async def test_diamond_dependency_all_built(
|
||||
|
|
@ -420,7 +422,7 @@ class TestRunBuild:
|
|||
}
|
||||
)
|
||||
with patch("bulkgen.builder._create_providers", return_value=_fake_providers()):
|
||||
result = await run_build(config, project_dir)
|
||||
result = await run_build(config, project_dir, _PROJECT)
|
||||
|
||||
assert set(result.built) == {"left.md", "right.md", "merge.txt"}
|
||||
assert result.failed == {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue