Skip to content

Commit c3e8ed8

Browse files
Create cfp_candidates.py
1 parent 482939b commit c3e8ed8

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

utils/cfp_candidates.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env python3
2+
"""Emit conference series that likely need a new edition checked.
3+
4+
A candidate is a series with no entry in _data/conferences.yml (nothing
5+
upcoming or TBA) whose latest archived edition is recent enough that the
6+
series is plausibly still alive. Output is JSON on stdout, newest first.
7+
8+
Intended for the cfp-scout routine: run once at session start, then work
9+
from the JSON instead of re-reading the data files.
10+
"""
11+
12+
import argparse
13+
import json
14+
from datetime import datetime, timezone
15+
from pathlib import Path
16+
17+
import yaml
18+
19+
CARRY_FIELDS = ("link", "place", "sub", "alt_name", "cfp_link")
20+
21+
22+
def load(path: Path) -> list[dict]:
23+
if not path.exists():
24+
return []
25+
with path.open() as fh:
26+
return yaml.safe_load(fh) or []
27+
28+
29+
def main() -> None:
30+
parser = argparse.ArgumentParser(description=__doc__)
31+
parser.add_argument(
32+
"--lookback",
33+
type=int,
34+
default=2,
35+
help="Only consider series whose latest edition is within this many years (default: 2)",
36+
)
37+
parser.add_argument("--base", type=Path, default=Path(), help="Repository root")
38+
args = parser.parse_args()
39+
40+
current_year = datetime.now(tz=timezone.utc).year
41+
cutoff = current_year - args.lookback
42+
43+
current_names = {c["conference"] for c in load(args.base / "_data/conferences.yml")}
44+
45+
latest: dict[str, dict] = {}
46+
for conf in load(args.base / "_data/archive.yml"):
47+
name = conf.get("conference")
48+
year = conf.get("year") or 0
49+
if not name or name in current_names:
50+
continue
51+
if year > latest.get(name, {}).get("latest_year", 0):
52+
entry = {"conference": name, "latest_year": year}
53+
entry.update({k: conf[k] for k in CARRY_FIELDS if conf.get(k)})
54+
latest[name] = entry
55+
56+
candidates = sorted(
57+
(info for info in latest.values() if info["latest_year"] >= cutoff),
58+
key=lambda x: (-x["latest_year"], x["conference"]),
59+
)
60+
print(json.dumps({"generated": f"{current_year}", "count": len(candidates), "candidates": candidates}, indent=2))
61+
62+
63+
if __name__ == "__main__":
64+
main()

0 commit comments

Comments
 (0)