Skip to content

Commit bc6c585

Browse files
authored
Merge pull request #53 from vitali87/fix/score-plan-groups
fix: read plan groups from the saved PlanFile in the score action
2 parents e4cc532 + 92101ac commit bc6c585

2 files changed

Lines changed: 72 additions & 4 deletions

File tree

scripts/score_pr.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ def _md_escape(s: str) -> str:
3535
return s.replace("|", "\\|")
3636

3737

38+
def load_plan_groups(plan_path: str) -> list[dict]:
39+
"""Return the groups from a saved plan file.
40+
41+
``pr-split --dry-run`` writes a ``PlanFile`` whose top-level keys are
42+
``plan`` and ``git_state``; the groups live under ``plan``.
43+
"""
44+
with open(plan_path) as f:
45+
data = json.load(f)
46+
plan = data.get("plan", data)
47+
return plan.get("groups", [])
48+
49+
3850
def _parse_int_env(name: str, default: int) -> int:
3951
raw = os.environ.get(name, str(default))
4052
try:
@@ -119,10 +131,7 @@ def main() -> None:
119131
_skip("No plan file generated.")
120132
return
121133

122-
with open(plan_path) as f:
123-
plan = json.load(f)
124-
125-
groups = plan.get("groups", [])
134+
groups = load_plan_groups(plan_path)
126135
total_groups = len(groups)
127136

128137
max_group_loc = max((g["estimated_loc"] for g in groups), default=0)

tests/test_score_pr.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from __future__ import annotations
2+
3+
import importlib.util
4+
import sys
5+
from pathlib import Path
6+
7+
from pr_split.constants import AssignmentType, Priority
8+
from pr_split.plan_store import PLAN_FILE
9+
from pr_split.schemas import GitState, Group, GroupAssignment, PlanFile, SplitPlan
10+
11+
SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "score_pr.py"
12+
13+
14+
def _load_script():
15+
spec = importlib.util.spec_from_file_location("score_pr", SCRIPT)
16+
module = importlib.util.module_from_spec(spec)
17+
assert spec.loader is not None
18+
sys.modules["score_pr"] = module
19+
spec.loader.exec_module(module)
20+
return module
21+
22+
23+
def _plan_file() -> PlanFile:
24+
group = Group(
25+
id="pr-1",
26+
title="t",
27+
description="d",
28+
assignments=[
29+
GroupAssignment(
30+
file_path="a.py",
31+
assignment_type=AssignmentType.WHOLE_FILE,
32+
hunk_indices=[0],
33+
)
34+
],
35+
estimated_loc=3,
36+
)
37+
plan = SplitPlan(
38+
dev_branch="feature",
39+
base_branch="main",
40+
max_loc=400,
41+
priority=Priority.ORTHOGONAL,
42+
groups=[group, group.model_copy(update={"id": "pr-2", "depends_on": ["pr-1"]})],
43+
)
44+
return PlanFile(plan=plan, git_state=GitState())
45+
46+
47+
class TestLoadPlanGroups:
48+
def test_reads_groups_from_saved_plan_file(self, tmp_path: Path) -> None:
49+
path = tmp_path / Path(PLAN_FILE).name
50+
path.write_text(_plan_file().model_dump_json())
51+
groups = _load_script().load_plan_groups(str(path))
52+
assert [g["id"] for g in groups] == ["pr-1", "pr-2"]
53+
assert groups[0]["assignments"][0]["file_path"] == "a.py"
54+
assert groups[1]["depends_on"] == ["pr-1"]
55+
56+
def test_accepts_bare_plan_document(self, tmp_path: Path) -> None:
57+
path = tmp_path / "plan.json"
58+
path.write_text(_plan_file().plan.model_dump_json())
59+
assert len(_load_script().load_plan_groups(str(path))) == 2

0 commit comments

Comments
 (0)