File size: 4,449 Bytes
4140be3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python3
"""
Annotate runtime environment for Bioconda tool JSON files.

Default targets:
- output/bioconda_source_tool/bioconda_t0_core_tools.json
- output/bioconda_source_tool/bioconda_t1_domain_tools.json
- output/bioconda_source_tool/bioconda_t2_on_demand_tools.json
"""

from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Dict, List, Tuple


def _lower_list(values: List[str]) -> List[str]:
    return [str(v).strip().lower() for v in values if str(v).strip()]


def infer_runtime(package_name: str, dependencies: List[str], summary: str, description: str) -> Tuple[str, str]:
    pkg = package_name.lower()
    deps = _lower_list(dependencies)
    text = f"{summary} {description}".lower()

    # Rule 1: R ecosystem
    if pkg.startswith("r-") or pkg.startswith("bioconductor-"):
        return "R", "package_name prefix indicates R/Bioconductor ecosystem"
    if any(d.startswith("r-") or "r-base" in d for d in deps):
        return "R", "dependencies include r-base or r-* packages"

    # Rule 2: Perl ecosystem
    if pkg.startswith("perl-") or any(d.startswith("perl-") or d == "perl" for d in deps):
        return "Perl", "package/dependencies indicate Perl runtime"

    # Rule 3: Java ecosystem
    if any("openjdk" in d or "default-jre" in d or d == "java" for d in deps):
        return "Java", "dependencies include Java runtime (openjdk/jre)"

    # Rule 4: Python ecosystem
    if any("python" in d for d in deps):
        return "Python", "dependencies include python"
    py_keywords = ("python", "pypi", "scanpy", "scvelo", "scvi", "anndata")
    if any(k in text for k in py_keywords):
        return "Python", "summary/description contains Python ecosystem keywords"

    # Rule 5: Mostly compiled binary style
    compiled_markers = ("libgcc", "libstdcxx", "htslib", "zlib", "gcc", "gxx")
    if any(any(m in d for m in compiled_markers) for d in deps):
        return "Compiled", "dependencies suggest compiled/native executable"

    return "Other", "no strong signal for Python/R/Perl/Java; marked as Other"


def annotate_file(json_path: Path, inplace: bool = True) -> Dict[str, int]:
    if not json_path.exists():
        return {"total": 0, "updated": 0}

    with json_path.open("r", encoding="utf-8") as f:
        rows = json.load(f)
    if not isinstance(rows, list):
        raise ValueError(f"JSON root must be list: {json_path}")

    updated = 0
    for row in rows:
        if not isinstance(row, dict):
            continue
        runtime, reason = infer_runtime(
            package_name=str(row.get("package_name", "")).strip(),
            dependencies=list(row.get("dependencies", []) or []),
            summary=str(row.get("summary", "")).strip(),
            description=str(row.get("description", "")).strip(),
        )
        row["execution_environment"] = runtime
        row["execution_environment_reason"] = reason
        updated += 1

    if inplace:
        with json_path.open("w", encoding="utf-8") as f:
            json.dump(rows, f, ensure_ascii=False, indent=2)

    return {"total": len(rows), "updated": updated}


def main() -> None:
    parser = argparse.ArgumentParser(description="Add execution environment annotations to tool JSON files.")
    parser.add_argument(
        "--files",
        nargs="*",
        default=[
            "/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/bioconda_t0_core_tools.json",
            "/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/bioconda_t1_domain_tools.json",
            "/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/bioconda_t2_on_demand_tools.json",
        ],
        help="Target JSON files.",
    )
    args = parser.parse_args()

    results = {}
    for p in args.files:
        path = Path(p)
        stats = annotate_file(path, inplace=True)
        results[str(path)] = stats
        print(f"{path}: updated {stats['updated']}/{stats['total']}")

    report_path = Path("/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/runtime_annotation_report.json")
    report_path.parent.mkdir(parents=True, exist_ok=True)
    with report_path.open("w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=2)
    print(f"Saved report: {report_path}")


if __name__ == "__main__":
    main()