Skip to content

Instantly share code, notes, and snippets.

@colindean
Created Apr 1, 2021
Embed
What would you like to do?
A Pythonic Makefile, Brewfile, and Poetry config
# basic build tool, get the latest version
# if you want to ensure use, use 'gmake' instead on macOS
# or follow caveats in `brew info make` to make make brew's make
brew 'make'
# python version and environment management
brew 'pyenv'
# python dependency manager
# a version from pypi instead of homebrew may be installed when running make deps
brew 'poetry'
# Set this to ~use it everywhere in the project setup
PYTHON_VERSION ?= 3.7.1
# the directories containing the library modules this repo builds
LIBRARY_DIRS = mylibrary
# build artifacts organized in this Makefile
BUILD_DIR ?= build
# PyTest options
PYTEST_HTML_OPTIONS = --html=$(BUILD_DIR)/report.html --self-contained-html
PYTEST_TAP_OPTIONS = --tap-combined --tap-outdir $(BUILD_DIR)
PYTEST_COVERAGE_OPTIONS = --cov=$(LIBRARY_DIRS)
PYTEST_OPTIONS ?= $(PYTEST_HTML_OPTIONS) $(PYTEST_TAP_OPTIONS) $(PYTEST_COVERAGE_OPTIONS)
# MyPy typechecking options
MYPY_OPTS ?= --python-version $(basename $(PYTHON_VERSION)) --show-column-numbers --pretty --html-report $(BUILD_DIR)/mypy
# Python installation artifacts
PYTHON_VERSION_FILE=.python-version
ifeq ($(shell which pyenv),)
# pyenv isn't installed, guess the eventual path FWIW
PYENV_VERSION_DIR ?= $(HOME)/.pyenv/versions/$(PYTHON_VERSION)
else
# pyenv is installed
PYENV_VERSION_DIR ?= $(shell pyenv root)/versions/$(PYTHON_VERSION)
endif
PIP ?= pip3
POETRY_OPTS ?=
POETRY ?= poetry $(POETRY_OPTS)
RUN_PYPKG_BIN = $(POETRY) run
COLOR_ORANGE = \033[33m
COLOR_RESET = \033[0m
##@ Utility
.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
.PHONY: version-python
version-python: ## Echos the version of Python in use
@echo $(PYTHON_VERSION)
##@ Testing
.PHONY: test
test: ## Runs tests
$(RUN_PYPKG_BIN) pytest \
$(PYTEST_OPTIONS) \
tests/*.py
##@ Building and Publishing
.PHONY: build
build: ## Runs a build
$(POETRY) build
.PHONY: publish
publish: ## Publish a build to the configured repo
$(POETRY) publish $(POETRY_PUBLISH_OPTIONS_SET_BY_CI_ENV)
.PHONY: deps-py-update
deps-py-update: pyproject.toml ## Update Poetry deps, e.g. after adding a new one manually
$(POETRY) update
##@ Setup
# dynamic-ish detection of Python installation directory with pyenv
$(PYENV_VERSION_DIR):
pyenv install --skip-existing $(PYTHON_VERSION)
$(PYTHON_VERSION_FILE): $(PYENV_VERSION_DIR)
pyenv local $(PYTHON_VERSION)
.PHONY: deps
deps: deps-brew deps-py ## Installs all dependencies
.PHONY: deps-brew
deps-brew: Brewfile ## Installs development dependencies from Homebrew
brew bundle --file=Brewfile
@echo "$(COLOR_ORANGE)Ensure that pyenv is setup in your shell.$(COLOR_RESET)"
@echo "$(COLOR_ORANGE)It should have something like 'eval \$$(pyenv init -)'$(COLOR_RESET)"
.PHONY: deps-py
deps-py: $(PYTHON_VERSION_FILE) ## Installs Python development and runtime dependencies
$(PIP) install --upgrade \
--index-url $(PYPI_PROXY) \
pip
$(PIP) install --upgrade \
--index-url $(PYPI_PROXY) \
poetry
$(POETRY) install
##@ Code Quality
.PHONY: check
check: check-py ## Runs linters and other important tools
.PHONY: check-py
check-py: check-py-flake8 check-py-black check-py-mypy ## Checks only Python files
.PHONY: check-py-flake8
check-py-flake8: ## Runs flake8 linter
$(RUN_PYPKG_BIN) flake8 .
.PHONY: check-py-black
check-py-black: ## Runs black in check mode (no changes)
$(RUN_PYPKG_BIN) black --check --line-length 118 --fast .
.PHONY: check-py-mypy
check-py-mypy: ## Runs mypy
$(RUN_PYPKG_BIN) mypy $(MYPY_OPTS) $(LIBRARY_DIRS)
.PHONY: format-py
format-py: ## Runs black, makes changes where necessary
$(RUN_PYPKG_BIN) black --line-length 118 .
[tool.poetry]
name = "XXXXXXX"
version = "0.0.0"
description = "XXXXXXX"
authors = [
"XXXXX <XXXX@XXXX.XXXX>"
]
license = "MIT"
[tool.poetry.dependencies]
python = "^3.9"
[tool.poetry.dev-dependencies]
flake8 = "*"
black = "*"
mypy = "*"
pytest = "*"
pytest-html = "*"
ansi2html = "*"
pytest-tap = "*"
pytest-cov = "*"
pytest-mypy = "*"
lxml = "*"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment