Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/graduation_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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).**

<!-- STEERING-MEMBERS -->
<!-- STEERING-CHECKLIST -->
@xhochy (Uwe Korn)
- [ ] yes
- [ ] no
Expand Down Expand Up @@ -168,7 +168,7 @@ body:
- [ ] yes
- [ ] no
- [ ] abstain
<!-- END-OF-STEERING-MEMBERS -->
<!-- END-OF-STEERING-CHECKLIST -->
```

**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).
44 changes: 42 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,14 +505,54 @@ Sufficient justification must be given as to why a Project Team member should be

In alphabetical order,

{{ steering_members }}
<!-- STEERING-TABLE -->
| 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 |
<!-- END-OF-STEERING-TABLE -->


## Emeritus Steering members

In alphabetical order,

{{ emeritus_members }}
<!-- EMERITUS-TABLE -->
| 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) | | |
<!-- END-OF-EMERITUS-TABLE -->


## Document History
Expand Down
2 changes: 1 addition & 1 deletion emeritus.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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,,
Expand Down
63 changes: 45 additions & 18 deletions scripts/sync_steering_members.py
Original file line number Diff line number Diff line change
@@ -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
<!-- STEERING-MEMBERS --> / <!-- END-OF-STEERING-MEMBERS --> 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:
<!-- STEERING-CHECKLIST --> / <!-- END-OF-STEERING-CHECKLIST -->
Vote checklist (yes/no/abstain per member) from steering.csv
<!-- STEERING-TABLE --> / <!-- END-OF-STEERING-TABLE -->
Markdown table of current members from steering.csv
<!-- EMERITUS-TABLE --> / <!-- END-OF-EMERITUS-TABLE -->
Markdown table of emeritus members from emeritus.csv

Usage:
python scripts/sync_steering_members.py # update files in-place
Expand All @@ -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 = "<!-- STEERING-MEMBERS -->"
END_MARKER = "<!-- END-OF-STEERING-MEMBERS -->"

MARKER_RE = re.compile(
rf"^(?P<indent>[ \t]*){re.escape(START_MARKER)}\n"
rf"(?P<body>.*?)"
rf"^(?P=indent){re.escape(END_MARKER)}",
r"^(?P<indent>[ \t]*)<!-- (?P<name>[A-Z-]+) -->\n"
r"(?P<body>.*?)"
r"^(?P=indent)<!-- END-OF-(?P=name) -->",
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):
Expand All @@ -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}<!-- {name} -->\n{indented}\n{indent}<!-- END-OF-{name} -->"

new_text = MARKER_RE.sub(_replace, text)
if new_text == text:
Expand All @@ -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("*")):
Expand All @@ -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:
Expand Down