Skip to content

pymake

Bundled with this library is a command called pymake which replicates the syntax and behavior of GNU make, but in Python.

Makefile.py example

import pipepy
from pipepy import python, rm

pipepy.set_always_stream(True)
pipepy.set_always_raise(True)

def clean():
    rm('-rf', "build", "dist")()

def build(clean):
    python('-m', "build")()

def publish(build):
    python('-m', "twine").upload("dist/*")()

Run pymake publish to run the publish target along with its dependencies. Function argument names define dependencies, so clean is a dependency of build and build is a dependency of publish.

(You don't have to use pipepy commands inside Makefile.py, but it's a very good fit.)

Return values

Arguments hold the return values of dependency targets:

def a():
    return 1

def b():
    return 2

def c(a, b):
    print(a + b)
pymake c
# ← 3

Single execution

Each dependency executes at most once, even if used multiple times:

def a():
    print("pymake target a")

def b(a):
    print("pymake target b")

def c(a, b):
    print("pymake target c")
pymake c
# ← pymake target a
# ← pymake target b
# ← pymake target c

Default target

Set DEFAULT_PYMAKE_TARGET to define the default target:

from pipepy import pytest

DEFAULT_PYMAKE_TARGET = "test"

def test():
    pytest(_stream=True)()
pymake  # runs the 'test' target

Variables

Apart from dependencies, function arguments can define variables overridden by the invocation:

Via function keyword arguments

# Makefile.py
def greeting(msg="world"):
    print(f"hello {msg}")
pymake greeting
# ← hello world

pymake greeting msg=Bill
# ← hello Bill

Via global variables

# Makefile.py
msg = "world"

def greeting():
    print(f"hello {msg}")
pymake greeting
# ← hello world

pymake greeting msg=Bill
# ← hello Bill

Shell completion

pymake supports shell completion for bash and zsh.

Bash

eval $(pymake --setup-bash-completion)
$ pymake <TAB><TAB>
build      clean      debugtest  publish    watchtest
checks     covtest    html       test

Zsh

eval $(pymake --setup-zsh-completion)
$ pymake <TAB>
build      -- Build package
checks     -- Run static checks on the code (flake8, isort)
clean      -- Clean up build directories
...

Descriptions are taken from the pymake targets' docstrings.

Put the eval statements in your .bashrc/.zshrc.