Single source of truth for dependency parsing, replacing three copies: - dev-poll.sh get_deps() now calls parse-deps.py - supervisor P3b/P3c import parse_deps() via importlib Supports stdin, argument, and --json modes for different callers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
59 lines
1.9 KiB
Python
Executable file
59 lines
1.9 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""Extract dependency issue numbers from an issue body.
|
|
|
|
Usage:
|
|
echo "$ISSUE_BODY" | python3 lib/parse-deps.py
|
|
python3 lib/parse-deps.py "$ISSUE_BODY"
|
|
python3 lib/parse-deps.py --json < issues.json
|
|
|
|
Modes:
|
|
stdin/arg: reads a single issue body, prints one dep number per line
|
|
--json: reads a JSON array of issues from stdin, prints JSON
|
|
dep graph: {"issue_num": [dep1, dep2], ...}
|
|
|
|
Matches the same logic as dev-poll.sh get_deps():
|
|
- Sections: ## Dependencies / ## Depends on / ## Blocked by
|
|
- Inline: "depends on #NNN" / "blocked by #NNN" anywhere
|
|
- Ignores: ## Related (safe for sibling cross-references)
|
|
"""
|
|
import json
|
|
import re
|
|
import sys
|
|
|
|
|
|
def parse_deps(body):
|
|
"""Return sorted list of unique dependency issue numbers from an issue body."""
|
|
deps = set()
|
|
in_section = False
|
|
for line in (body or "").split("\n"):
|
|
if re.match(r"^##?\s*(Depends on|Blocked by|Dependencies)", line, re.IGNORECASE):
|
|
in_section = True
|
|
continue
|
|
if in_section and re.match(r"^##?\s", line):
|
|
in_section = False
|
|
if in_section:
|
|
deps.update(int(m) for m in re.findall(r"#(\d+)", line))
|
|
if re.search(r"(depends on|blocked by)", line, re.IGNORECASE):
|
|
deps.update(int(m) for m in re.findall(r"#(\d+)", line))
|
|
return sorted(deps)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) > 1 and sys.argv[1] == "--json":
|
|
issues = json.load(sys.stdin)
|
|
graph = {}
|
|
for issue in issues:
|
|
num = issue["number"]
|
|
deps = parse_deps(issue.get("body", ""))
|
|
deps = [d for d in deps if d != num]
|
|
if deps:
|
|
graph[num] = deps
|
|
json.dump(graph, sys.stdout)
|
|
print()
|
|
else:
|
|
if len(sys.argv) > 1:
|
|
body = sys.argv[1]
|
|
else:
|
|
body = sys.stdin.read()
|
|
for dep in parse_deps(body):
|
|
print(dep)
|