diff --git a/.github/ISSUE_TEMPLATE/graduation_request.yml b/.github/ISSUE_TEMPLATE/graduation_request.yml index 5f29ca1..a4d4043 100644 --- a/.github/ISSUE_TEMPLATE/graduation_request.yml +++ b/.github/ISSUE_TEMPLATE/graduation_request.yml @@ -103,7 +103,7 @@ body: **This vote will end on YYYY-MM-DD, End of Day, [Anywhere on Earth](https://time.is/Anywhere_on_Earth) (AoE).** - + @xhochy (Uwe Korn) - [ ] yes - [ ] no @@ -168,7 +168,7 @@ body: - [ ] yes - [ ] no - [ ] abstain - + ``` **If quorum may be low:** before using [timeout](https://github.com/conda/governance#quorum) rules, the vote must run ≥2 weeks, be discussed at a Steering Council meeting, and get ≥3 Slack + ≥3 email reminders (see `steering.csv` emails). Timeout outcomes need a PR under [`vote-results/`](https://github.com/conda/governance/tree/main/vote-results). diff --git a/README.md b/README.md index d666792..ba86cba 100644 --- a/README.md +++ b/README.md @@ -505,14 +505,54 @@ Sufficient justification must be given as to why a Project Team member should be In alphabetical order, -{{ steering_members }} + +| Name | GitHub | Funder | Pronouns | +| --- | --- | --- | --- | +| Bas Zalmstra | [@baszalmstra](https://github.com/baszalmstra) | prefix.dev | he/him | +| Cheng H. Lee | [@chenghlee](https://github.com/chenghlee) | Anaconda | he/him | +| Filipe Fernandes | [@ocefpaf](https://github.com/ocefpaf) | no funding | he/him | +| Hind Montassif | [@Hind-M](https://github.com/Hind-M) | QuantStack | she/her | +| Jaime Rodríguez-Guerra | [@jaimergp](https://github.com/jaimergp) | Quansight | he/him | +| Jannis Leidel | [@jezdez](https://github.com/jezdez) | Anaconda | he/him | +| John Kirkham | [@jakirkham](https://github.com/jakirkham) | NVIDIA | he/him | +| Marcelo Duarte Trevisani | [@marcelotrevisani](https://github.com/marcelotrevisani) | no funding | he/him | +| Marius van Niekerk | [@mariusvniekerk](https://github.com/mariusvniekerk) | | | +| Michael Sarahan | [@msarahan](https://github.com/msarahan) | NVIDIA | he/him | +| Pavel Zwerschke | [@pavelzw](https://github.com/pavelzw) | QuantCo | he/him | +| Uwe Korn | [@xhochy](https://github.com/xhochy) | QuantCo | he/him | +| Wolf Vollprecht | [@wolfv](https://github.com/wolfv) | prefix.dev | he/him | + ## Emeritus Steering members In alphabetical order, -{{ emeritus_members }} + +| Name | GitHub | Funder | Pronouns | +| --- | --- | --- | --- | +| Angela Gloyna | [@angloyna](https://github.com/angloyna) | | | +| Anthony Scopatz | [@scopatz](https://github.com/scopatz) | | | +| Christopher J. 'CJ' Wright | [@cj-wright](https://github.com/cj-wright) | | | +| Connor Martin | [@cjmartian](https://github.com/cjmartian) | | | +| Crystal Soja | [@csoja](https://github.com/csoja) | | | +| Dharhas Pothina | [@dharhas](https://github.com/dharhas) | | | +| Eric Dill | [@ericdill](https://github.com/ericdill) | | | +| Gonzalo Peña-Castellanos | [@goanpeca](https://github.com/goanpeca) | Quansight | he/him | +| Jonathan Helmus | [@jjhelmus](https://github.com/jjhelmus) | | | +| Keith Kraus | [@kkraus14](https://github.com/kkraus14) | no funding | he/him | +| Marcel Bargull | [@mbargull](https://github.com/mbargull) | | | +| Martin Prüsse | [@prusse-martin](https://github.com/prusse-martin) | | | +| Matthew R. Becker | [@beckermr](https://github.com/beckermr) | no funding | he/him | +| Megan Yancy | [@myancy-anaconda](https://github.com/myancy-anaconda) | | | +| Michael Grant | [@mcg1969](https://github.com/mcg1969) | | | +| Min Ragan-Kelley | [@minrk](https://github.com/minrk) | | | +| Patrick Sodré | [@sodre](https://github.com/sodre) | | | +| Ray Douglass | [@raydouglass](https://github.com/raydouglass) | | | +| Sebastien Awwad | [@awwad](https://github.com/awwad) | | | +| Tania Allard | [@trallard](https://github.com/trallard) | Quansight | she/her | +| Travis Oliphant | [@teoliphant](https://github.com/teoliphant) | | | + ## Document History diff --git a/emeritus.csv b/emeritus.csv index 01b0452..cc68e54 100644 --- a/emeritus.csv +++ b/emeritus.csv @@ -15,7 +15,7 @@ csoja,csoja@anaconda.com,Crystal Soja,, awwad,sebastien.awwad@gmail.com,Sebastien Awwad,, ericdill,ericdill@pm.me,Eric Dill,, goanpeca,goanpeca@gmail.com,Gonzalo Peña-Castellanos,Quansight,he/him -kkraus14,keith.j.kraus@gmail.com,Keith Kraus,no funding, he/him +kkraus14,keith.j.kraus@gmail.com,Keith Kraus,no funding,he/him beckermr,becker.mr@gmail.com,Matthew R. Becker,no funding,he/him trallard,taniar.allard@gmail.com,Tania Allard,Quansight,she/her cj-wright,cjwright4242@gmail.com,Christopher J. 'CJ' Wright,, diff --git a/scripts/sync_steering_members.py b/scripts/sync_steering_members.py index 08b043e..74f5bce 100644 --- a/scripts/sync_steering_members.py +++ b/scripts/sync_steering_members.py @@ -1,8 +1,15 @@ -"""Replace content between STEERING-MEMBERS markers with the current steering.csv list. +"""Sync steering council data from CSV files into marker-delimited sections. -Scans .yml, .yaml, and .md files under the repo root for - / marker pairs and -regenerates the vote checklist between them, preserving the surrounding indentation. +Scans .yml, .yaml, and .md files under the repo root for marker pairs and +regenerates content between them, preserving the surrounding indentation. + +Supported markers: + / + Vote checklist (yes/no/abstain per member) from steering.csv + / + Markdown table of current members from steering.csv + / + Markdown table of emeritus members from emeritus.csv Usage: python scripts/sync_steering_members.py # update files in-place @@ -16,22 +23,20 @@ REPO_ROOT = Path(__file__).resolve().parents[1] STEERING_CSV = REPO_ROOT / "steering.csv" +EMERITUS_CSV = REPO_ROOT / "emeritus.csv" EXTENSIONS = {".yml", ".yaml", ".md"} -START_MARKER = "" -END_MARKER = "" - MARKER_RE = re.compile( - rf"^(?P[ \t]*){re.escape(START_MARKER)}\n" - rf"(?P.*?)" - rf"^(?P=indent){re.escape(END_MARKER)}", + r"^(?P[ \t]*)\n" + r"(?P.*?)" + r"^(?P=indent)", re.MULTILINE | re.DOTALL, ) def build_checklist(csv_path: Path) -> str: - """Return the bare checklist lines (no leading indent, no markers).""" + """Return per-member vote checklist lines (yes/no/abstain).""" lines: list[str] = [] with csv_path.open(newline="") as f: for row in csv.DictReader(f): @@ -45,18 +50,36 @@ def build_checklist(csv_path: Path) -> str: return "\n".join(lines) -def sync_file(path: Path, checklist: str, *, check: bool) -> bool: +def build_table(csv_path: Path) -> str: + """Return a markdown table of members sorted alphabetically by first name.""" + with csv_path.open(newline="") as f: + rows = sorted(csv.DictReader(f), key=lambda r: r["name"].lower()) + + lines = ["| Name | GitHub | Funder | Pronouns |", "| --- | --- | --- | --- |"] + for row in rows: + name = row["name"] + username = row["github_username"] + funder = row.get("funder", "") or "" + pronouns = row.get("pronouns", "") or "" + lines.append( + f"| {name} | [@{username}](https://github.com/{username}) | {funder} | {pronouns} |" + ) + return "\n".join(lines) + + +def sync_file(path: Path, contents: dict[str, str], *, check: bool) -> bool: """Sync one file. Returns True if the file was (or would be) changed.""" text = path.read_text() - if START_MARKER not in text: - return False def _replace(m: re.Match) -> str: + name = m.group("name") + if name not in contents: + return m.group(0) indent = m.group("indent") indented = "\n".join( - f"{indent}{line}" if line else "" for line in checklist.splitlines() + f"{indent}{line}" if line else "" for line in contents[name].splitlines() ) - return f"{indent}{START_MARKER}\n{indented}\n{indent}{END_MARKER}" + return f"{indent}\n{indented}\n{indent}" new_text = MARKER_RE.sub(_replace, text) if new_text == text: @@ -69,7 +92,11 @@ def _replace(m: re.Match) -> str: def main() -> int: check = "--check" in sys.argv - checklist = build_checklist(STEERING_CSV) + contents = { + "STEERING-CHECKLIST": build_checklist(STEERING_CSV), + "STEERING-TABLE": build_table(STEERING_CSV), + "EMERITUS-TABLE": build_table(EMERITUS_CSV), + } changed: list[Path] = [] for path in sorted(REPO_ROOT.rglob("*")): @@ -79,7 +106,7 @@ def main() -> int: continue if ".git" in path.parts: continue - if sync_file(path, checklist, check=check): + if sync_file(path, contents, check=check): changed.append(path) if changed: