Skip to content

Instantly share code, notes, and snippets.

@mwcraig
Created June 25, 2026 16:57
Show Gist options
  • Select an option

  • Save mwcraig/d3daa224d3f28cc374efe25ac813cbce to your computer and use it in GitHub Desktop.

Select an option

Save mwcraig/d3daa224d3f28cc374efe25ac813cbce to your computer and use it in GitHub Desktop.
SciPy 2026 Tutorial Installation Instructors markdown generator
#!/usr/bin/env python3
"""Generate a nicely formatted Markdown file from the SciPy 2026 Tutorials CSV."""
import csv
import re
from pathlib import Path
CSV_PATH = Path("SciPy 2026 Tutorials - Installation instruction + content links.csv")
MD_PATH = Path("SciPy 2026 Tutorials.md")
URL_RE = re.compile(r"https?://\S+")
# Placeholder notes that mean "no real instructions yet" — these get italicized.
PLACEHOLDER_RE = re.compile(
r"^(none|n/?a|tbd|tba|todo|coming soon|to be (added|determined|announced))"
r"\b.*$",
re.IGNORECASE,
)
def linkify(text):
"""Turn each URL in `text` into a Markdown autolink.
We use the angle-bracket autolink form `<url>` rather than `[url](url)`.
Pandoc renders `<url>` as LaTeX `\\url{}`, which knows how to break long
URLs across lines (at slashes/dots) while keeping the whole thing one
clickable link. `[url](url)` becomes `\\href{}{}` whose visible text is an
unbreakable word, so wrapped fragments fall outside the link in PDFs.
"""
def repl(match):
url = match.group(0)
# Don't let trailing punctuation get swallowed into the link.
trailing = ""
while url and url[-1] in ".,;:)]}":
trailing = url[-1] + trailing
url = url[:-1]
return f"<{url}>" + trailing
return URL_RE.sub(repl, text)
def render_installation(cell):
text = cell.strip()
if not text:
return "_None provided yet_"
# A bare, single URL.
if URL_RE.fullmatch(text):
return f"<{text}>"
# Text with one or more embedded URLs.
if URL_RE.search(text):
return linkify(text)
# A placeholder note that means there's nothing real yet.
if PLACEHOLDER_RE.match(text):
return f"_{text}_"
# Real plain-text instructions: leave as-is.
return text
def render_presenters(cell):
names = [line.strip() for line in cell.splitlines() if line.strip()]
return ", ".join(names)
def main():
sections = []
with CSV_PATH.open(newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
title = row["Tutorial"].strip()
presenters = render_presenters(row["Presenters"])
installation = render_installation(row["Installation instructions"])
sections.append(
f"## {title}\n\n"
f"**Presenters:** {presenters}\n\n"
f"**Installation:** {installation}\n"
)
# YAML metadata so `pandoc` colors links in the PDF (hyperref colorlinks).
front_matter = (
"---\n"
"colorlinks: true\n"
"urlcolor: blue\n"
"linkcolor: blue\n"
"---\n\n"
)
md = (
front_matter
+ "# SciPy 2026 Tutorials — Installation Instructions\n\n"
+ "\n".join(sections)
)
MD_PATH.write_text(md, encoding="utf-8")
print(f"Wrote {len(sections)} tutorials to {MD_PATH}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment