skip to content
Back

Creating a Homebrew Tap for Python Packages

/ 3 min read

Updated:

I wanted to contribute to AnswerDotAI’s shell_sage repo, but their dependencies puzzled me. They compiled their code from Jupyter notebooks, which I had never done before.

So I forked the repo and rewrote the code in Python scripts.

Since the target audience is sysadmins, I figured it would be best to package it as a Homebrew formula.

Simpler said than done.

I spent an entire Sunday fighting dependencies.

Close to the end of the day, I found Simon Willison’s guide.

So, if you want to create your own Homebrew tap, please first read his post.

Here are a few of my own notes that might help you.

Setting Up Your Homebrew Tap

  1. Create a new GitHub repository with the naming convention homebrew-[tapname]

    Terminal window
    # Example: homebrew-shell-sage
  2. In this repository, create a Formula directory that will contain your .rb formula file

    Terminal window
    mkdir Formula

Creating the Formula

  1. Create your formula file in the Formula directory (e.g., shell_sage.rb)
  2. Basic structure should include:
    • Class definition (CamelCase)
    • Python virtualenv inclusion
    • Description and metadata
    • Dependencies
    • Resources (Python packages)
    • Installation method
    • Test block

Iterative Dependency Management

Like I said above, dependencies were a bitch.

Here’s how I did it in the end and how you should do it from the start:

  1. Start with a minimal formula containing just your main package:

    class ShellSage < Formula
    include Language::Python::Virtualenv
    desc "Your description"
    homepage "Your homepage"
    url "Your package URL"
    sha256 "Your SHA256"
    depends_on "python@3.12" # Or your required Python version
    def install
    virtualenv_install_with_resources
    end
    end

    I was a little bit confused how to get the sha256 for the package, because I had the .rb file and the python package in the same repo.

    I followed Simon’s advice and created two separate repos: one for the formula and one for the python package.

    The url points to a “release” of the python package. You can create the release manually or use the GitHub CLI.

    Terminal window
    gh release create v0.1.0 --generate-notes # run in your terminal in the python package repo

    You can find my releases here.

    I auto-create them when I push a new commit to the main branch.

    When you create a release, you also need to update the url and sha256 in the formula file`

    You can get the sha256 with:

    Terminal window
    curl -L https://github.com/nicolaygerold/homebrew-shell-sage/archive/refs/tags/v0.0.1.tar.gz | shasum -a 256

    This pipes the release into the shasum command to get the hash.

  2. To be honest. Dependencies were a bitch. Each library has a few dependencies, which have to be included in the formula.

    The fastest way to figure out the dependencies is to install the formula locally with brew.

    Terminal window
    brew install --build-from-source ./Formula/shell_sage.rb

    You will see a list of missing dependencies in the error message.

    Often you add one dependency and find that it has another dependency.

  3. Add each missing dependency as a resource block:

    resource "package_name" do
    url "PyPI URL for the package"
    sha256 "SHA256 for the package"
    end

Making Your Package Available

  1. Push your formula to your homebrew tap repository

  2. Tap your repository:

    Terminal window
    brew tap nicolaygerold/shell-sage
  3. Users can then install your package using something like:

    Terminal window
    brew install nicolaygerold/shell-sage/shell_sage

Good luck!