File size: 3,499 Bytes
cc857c8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import json, re, subprocess, sys
from collections import Counter
from datetime import datetime, timezone

prs = json.load(open(sys.argv[1]))
closed = set(int(l.split()[0]) for l in open("close_fail.log")) if False else set()
done = set(int(m) for m in re.findall(r"close (\d+)", open("cmds.sh").read()))
main = set(subprocess.run(["git", "-C", "/Users/arthurzucker/Work/transformers", "ls-tree", "-r", "--name-only", "origin/main"],
                          capture_output=True, text=True).stdout.split())
NOW = datetime(2026, 10, 20, tzinfo=timezone.utc)
age = lambda s: (NOW - datetime.fromisoformat(s.replace("Z", "+00:00"))).days
PHIL = [(re.compile(r"modeling_(tf|flax)_|_tf_utils|_flax_utils|/tf_|/flax_"), "TF/Flax code (removed in v5)"),
        (re.compile(r"^examples/research_projects/|^examples/legacy/|^templates/|^examples/(tensorflow|flax)/"), "removed/legacy examples or templates"),
        (re.compile(r"^src/transformers/models/deprecated/"), "deprecated model"),
        (re.compile(r"^src/transformers/(benchmark|onnx|commands/(pt_to_tf|convert))/"), "removed subsystem (benchmark/onnx/pt_to_tf)")]

out = []
for p in prs:
    if p["number"] in done: continue
    files = [f["path"] for f in p["files"]["nodes"]]
    last_commit = age(p["commits"]["nodes"][0]["commit"]["committedDate"]) if p["commits"]["nodes"] else 9999
    upd = age(p["updatedAt"])
    # new modeling files added count as present only if PR adds them; missing = existing-path edits that vanished
    missing = [f for f in files if f not in main and not re.search(r"models/[^/]+/(modeling|modular|configuration|processing|image_processing|tokenization|convert)_|^tests/models/|^docs/", f)]
    reasons, cats = [], set()
    if p["baseRefName"] != "main":
        cats.add("old_branch"); reasons.append(f"base branch is `{p['baseRefName']}`")
    if files and len(missing) / len(files) >= 0.5:
        cats.add("old_branch"); reasons.append(f"{len(missing)}/{len(files)} touched files no longer exist on main")
    for rx, why in PHIL:
        hits = [f for f in files if rx.search(f)]
        if hits: cats.add("philosophy"); reasons.append(f"{why}: {hits[0]}" + (f" (+{len(hits)-1})" if len(hits) > 1 else ""))
    if last_commit > 365 and upd > 90:
        cats.add("outdated"); reasons.append(f"last commit {last_commit}d ago, last activity {upd}d ago")
    elif p["mergeable"] == "CONFLICTING" and last_commit > 180 and upd > 60:
        cats.add("outdated"); reasons.append(f"merge conflicts, last commit {last_commit}d ago")
    if cats:
        out.append({"number": p["number"], "title": p["title"], "author": (p["author"] or {}).get("login"),
                    "assoc": p["authorAssociation"], "draft": p["isDraft"], "base": p["baseRefName"],
                    "mergeable": p["mergeable"], "review": p["reviewDecision"], "created": p["createdAt"][:10],
                    "last_commit_days": last_commit, "updated_days": upd, "labels": [l["name"] for l in p["labels"]["nodes"]],
                    "files": files[:15], "nfiles": p["files"]["totalCount"], "cats": sorted(cats), "signals": reasons,
                    "last_comments": [{"by": (c["author"] or {}).get("login"), "assoc": c["authorAssociation"], "at": c["createdAt"][:10], "text": c["body"][:300]} for c in p["comments"]["nodes"]]})
json.dump(out, open(sys.argv[2], "w"), indent=1)
print(len(prs), "open PRs ->", len(out), "flagged;", Counter(c for o in out for c in o["cats"]))
print("assoc:", Counter(o["assoc"] for o in out))