Skip to article frontmatterSkip to article content

Blog

2i2c
Project Jupyter

Below are a few of the latest posts in my blog. You can see a full list by year to the left.

The slow boring of hard boards in open source

Max Weber famously wrote that politics is "a strong and slow boring of hard boards." In [Why it took 4 years to get a lock files specification](https://snarky.ca/why-it-took-4-years-to-get-a-lock-files-specification/), Brett Cannon demonstrates how the same principle applies to technical coordination in open source. Python recently adopted [PEP 751](https://peps.python.org/pep-0751/) for lockfile specification. Doing so

Date: October 21, 2025 | Author: Chris Holdgraf
My system for beating jet lag

I travel internationally a lot, which means I deal with a lot of jet lag. This post is a quick summary of a system I've found helpful, based on [this paper](https://www.frontiersin.org/articles/10.3389/fphys.2019.00927/full). The basic idea is to shift your body's internal clock by timing your exposure to light, exercise, and melatonin around

Date: October 18, 2025 | Author: Chris Holdgraf
Why open source foundations try to fund systems, not development

This is a brief reflection on something that I've been hearing consistently from the Linux Foundation and its member projects as part of serving on the [Board of the Jupyter Foundation](https://jupyterfoundation.org). Here's a point that originally surprised me when I heard it: > Most foundations within the Linux Foundation network recommend

Date: May 31, 2025 | Author: Chris Holdgraf
Jupyter can align the needs of its community and its foundation by enabling contribution

This week was my first time attending the [Linux Foundation Member Summit](https://events.linuxfoundation.org/lf-member-summit/). This is an annual meeting for all of the Linux Foundation member organizations and projects. I joined because of my new role [on the Jupyter Executive Council](./jec.md), and so I tried to go into this meeting with the

Date: March 22, 2025 | Author: Chris Holdgraf
The relationship between the Jupyter Executive Council, Software Steering Council, and Foundation

This is a question that I've been asked many times now that I'm serving on the JEC and the JF. I'm writing up a quick response so that I have something to refer back to and align my own thinking on. **How most Linux Foundation projects seem to be structured**. Linux

Date: March 02, 2025 | Author: Chris Holdgraf
Ways the Jupyter Foundation could support open source projects

The Jupyter Foundation has a pot of money and it aims to use that funding quickly to support the Jupyter Project. But what should it use the funding _for_? There are many things to do, and not enough time or money to try everything. This is a brief brainstorm and

Date: February 26, 2025 | Author: Chris Holdgraf
Why I'm running for the Jupyter Executive Council

This year, I decided to nominate myself for the [Jupyter Executive Council](https://jupyter.org/governance/executive_council.html). This is a brief post explaining my rationale for doing so, the kind of service I'd hope to provide the project, and where I imagine the project moving. The [Jupyter Executive Council](https://jupyter.org/governance/executive_council.html) is the highest governing body within the

Date: January 14, 2025 | Author: Chris Holdgraf
How I'm trying to use BlueSky without getting burned again

Some quick thoughts on moving from Twitter/X to BlueSky and how I'll try to use social media after being burned once by Twitter.

Date: November 22, 2024 | Author: Chris Holdgraf
Better blog lists with the MyST AST

On my journey to learn more about writing with [the new MyST engine](https:///mystmd.org), I built upon [my recent update to my blog infrastructure](./programmatic-myst-with-jupyter.md) and made some improvements to my blog post list. Here's what it looks like now: ````{note} Click here to see how it looks now :class: dropdown ```{postlist} :number: 3 ``` ```` Here's a quick rundown

Date: November 09, 2024 | Author: Chris Holdgraf
Generate MyST with Jupyter and insert it into content programmatically

While I've been [converting my blog to use the new MyST engine](./mystmd-with-the-blog.md), I discovered a useful MyST feature. It's not yet possible to [natively parse Jupyter Markdown outputs as MyST](https://github.com/jupyter-book/mystmd/issues/1026) but there's a workaround if you don't mind generating a temporary file. The trick is to _write to a temporary file_

Date: November 04, 2024 | Author: Chris Holdgraf
Re-building my blog with MySTMD

Wow it has been a long time since I've last-written here. It turns out that having two small children and a very demanding job means you don't have as much time for blogging. But that's a whole different blog post... I've decided to convert my blog to use the new [MyST

Date: November 01, 2024 | Author: Chris Holdgraf
A few random opportunities in AI for Social Good

Recently a few friends have reached out asking if I knew of any opportunities to work on AI-related things that also have some kind of pro-social tie-in. I think a lof people see AI as a technology with a lot of potential, but in an environment of companies that don't seem

Date: October 02, 2023 | Author: Chris Holdgraf
A Sphinx directive for social media embeds

:::{note} This probably doesn't work anymore I've since moved my blog to use [the MyST Document Engine](https://mystmd.org) so this example will no longer work on my personal blog. See [this permalink for the latest working version](https://github.com/choldgraf/choldgraf.github.io/blob/ae8ee9792c74aac72f46c645d19352abc439d572/blog/2023/social-directive.md). ::: I often want to link to social and other types of web-based media in my Sphinx

Date: February 15, 2023 | Author: Chris Holdgraf
Report from FOSDEM23: beautiful chaos in a conference

I recently attended [FOSDEM 2023](https://fosdem.org/2023/), my first FOSDEM! I had heard of the conference before, but hadn't really looked into it too much. Fortunately, after some urging from friends and social media, I took a deeper look and decided I should join to see what all the fuss was about. Here are a

Date: February 06, 2023 | Author: Chris Holdgraf
Bundle extensions with your Sphinx theme

Sphinx is great because it has a ton of useful extensions that let you grow its functionality. However, a downside of this is that users have to actually _learn about_ those extensions and activate them manually. It's not hard, but it's a non-trivial amount of discovery work. One way to solve this is

Date: January 19, 2023 | Author: Chris Holdgraf
Install dependencies from GitHub with `pyproject.toml` or `requirements.txt`

This is a short post to demonstrate how to install packages directly from GitHub with `pyprojects.toml` or `requirements.txt`, including custom branches and commits. It will focus on `pyprojects.toml` because this is newer and there's less information about it, but the general pattern holds for `requirements.txt` as well. In `pyproject.toml`, you can specify

Date: December 31, 2022 | Author: Chris Holdgraf
Report from the JupyterLite workshop: WebAssembly is pretty cool

I recently attended [the JupyterLite community workshop in Paris](https://blog.jupyter.org/community-workshop-jupyterlite-e992c61f5d7f?source=collection_home---6------6-----------------------), here are some quick thoughts from the three-day event[^ack]. [^ack]: Many thanks to the [QuantStack](http://quantstack.com/) team for organizing this event, and to [OVHCloud](https://www.ovhcloud.com/en/) for providing a physical space for everyone. For those without any background, JupyterLite is a distribution of Jupyter's user

Date: December 10, 2022 | Author: Chris Holdgraf
Load and plot a remote font with Matplotlib

As part of [my `sphinx-social-previews`](https://github.com/choldgraf/sphinx-social-previews) prototype, I wanted to be able to use the [Roboto Font from Google](https://fonts.google.com/specimen/Roboto) in image previews. However, Roboto is often not loaded on your local filesystem, so it took some digging to figure out how to make it possible to load via [Matplotlib's text plotting functionality](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html). Here's

Date: December 06, 2022 | Author: Chris Holdgraf
How to update Sphinx options during the build

As part of [the `pydata-sphinx-theme`](https://github.com/pydata/pydata-sphinx-theme/pull/1075) we have a few settings that auto-enable extensions and configure them on behalf of the user. It has always been mysterious to me how to do this properly **during the Sphinx build**. It's easy to configure things with `conf.py` ahead of time, but what if you want

Date: December 05, 2022 | Author: Chris Holdgraf
Automatically update pre-commit hook versions

I figured out a way to automatically update all of the git `pre-commit` hook versions at once! [`pre-commit`](https://pre-commit.com/) is a useful command line tool for running simple commands before every `git` commit. I use it to enforce things like [`flake8`](https://flake8.pycqa.org/) and [`black`](https://github.com/psf/black) in many of my projects. However, I find it really annoying

Date: December 03, 2022 | Author: Chris Holdgraf
`subprocess.run` can execute shell commands directly

I often run shell commands in Python via the [`subprocess.run` command](https://docs.python.org/3/library/subprocess.html#subprocess.run). One thing that has always bugged me is that this required you to split commands into a list before it'd work properly. For example, you'd have to do: ```python import subprocess import shlex subprocess.run(*shlex.split("ls -l")) ``` Today I discovered that you don't have to do this! There's a

Date: November 29, 2022 | Author: Chris Holdgraf
Fix phantom GitHub workflows in your ci-cd with protected branch rules

Have you ever had a GitHub pull request show "phantom" workflows that never pass? This looks like one or more workflows that are in a constant **waiting state**, with a yellow status indicator, and that never complete. It looks something like this: ```{image} https://user-images.githubusercontent.com/1839645/204134864-da2541f0-ff4f-4d9f-8c80-aa8c4437d8a0.png ``` If you run into this, it may be because of

Date: November 27, 2022 | Author: Chris Holdgraf
Custom roles and domains in Sphinx with one line

I was working on [the roles and structure section of the 2i2c Team Compass](https://compass.2i2c.org) and found a nifty feature in Sphinx that I hadn't known before. You can currently add labels to any section with the following MyST Markdown structure: ```md (mylabel)= And now I [reference it](mylabel). ``` However, there are no **semantics** attached to this

Date: November 21, 2022 | Author: Chris Holdgraf
Automatically updating my publications page with ORCID and doi.org

For a while I've had a hand-crafted `.bibtex` file stored locally for [my `publications/` page](../../publications.md). However, manually updating local text file is a pain to remember, especially since there are many services out there that automatically track new publications. :::{admonition} Update! A [helpful suggestion on Twitter](https://twitter.com/temorrell/status/1594749942316208128) allowed me to include the full citation

Date: November 19, 2022 | Author: Chris Holdgraf
Automatically redirect folders in Sphinx websites

I spent a bit of time today updating my website after some changes in the MyST-NB and Sphinx Design ecosystems. Along the way, I decided to redirect `/posts/` to `/blog/`, since it seems `/blog/` is a much more common folder to use for blog posts. This posed a problem, because [the `sphinx-rediraffe`

Date: November 19, 2022 | Author: Chris Holdgraf