Package a dist
At the simplest point we want some source code to get made into a package we can then distribute.
flowchart LR
source
pyproject.toml --> poetry.lock
poetry.lock --> libs
source ----> dist[dist\nwhl - 'compiled'\ntar.gz - source]
libs --> dist
meta[Other assets\nREADME.md\nfiles, images\nicons etc.] ----> dist
Simple layout:
.
├── ./dist
├── ./.env
├── ./.flake8
├── ./kmpycore
│ └── ./kmpycore/__init__.py
├── ./Makefile
├── ./pip-requirements.txt
├── ./poetry.lock
├── ./pyproject.toml
├── ./README.md
├── ./tests
│ ├── ./tests/assets
│ │ └── ./tests/assets/file1.xml
│ └── ./tests/__init__.py
└── ./.vscode
└── ./.vscode/launch.json
pyproject.toml
At the most simple we need a name for the package and a version.
[tool.poetry]
name = "kmpycore" # matches folder we are in (can use - in name?)
version = "0.1.0"
description = "Keith's generally useful bits n bobs"
authors = ["Keith Marston <keith@sneconsulting.co.uk>"]
license = "MIT"
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.8,<3.12"
[tool.poetry.group.dev.dependencies]
black = "^23.3.0"
flake8 = "^4.0.1"
mypy = "^1.3.0"
isort = "^5"
pytest = "^7"
coverage = "^7"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
If we are in a pipeline that is going to publish the distribution we need to bump the minor version with poetry before making the dists. This is a problem for later though.
From this we can use poetry to create a lock file based on the required versions - this then also goes in version control even though it is a generated file it means you need to make a consouse decision to move forward a version of a dependant libary.
Use a Makefile
But wait how do we install python, what version of pip are we using and how do we install poetry. This is all required before we even make the distribution. First lets do some nice helpful bits in our make file...
#!make
include .env
export $(shell sed 's/=.*//' .env)
# Get first name = from pyproject
NAME := $(shell grep '^name = ' pyproject.toml | head -1 | cut -d \" -f2)
INSTALL_STAMP := .install.stamp
POETRY := $(shell command -v poetry 2> /dev/null)
.DEFAULT_GOAL := help
.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
And then move on to an install step followed by a package step.
At this stage we are potentially just quickly knocking up a local package - so we won't even worry about the full lintter process running as that can be annoying. Maybe put format then linit in the pre push hooks, or format as a minium.
To keep our workflow consistent we will use a Makefile so the same process is used to create the package in the pipeline as on our local machine.
Makefile advantages
Basline for a basic Python project and Makefile
https://python-poetry.org/docs/basic-usage/
Now lets consider formating and linters
Formatting is good for merge compares as general search of your code base.
Before a merge a format should be performed probably in a pre commit hook:
make format
and then we can lint before the merge / down vote the merge if it is not onto a protected branch.
The point here been a prtected branch should be "protected" from code that fails a lint but a feature branch can have trial code merged but a thread to resolve raised if it does not lint.
pre-commit checks
Lets make sure we always have formated code going into our repo.
How to post the merge issue / auto review coment
non-protected branch
make lint
So now we have a "thing" that needs a level of testing before been publish on any debug/development packaging server as if it does not pass our unit tests then what is the point of doing any further testing? Utimatly from a coding team point of view the process is?...??
flowchart LR
newCode --> MergeRequest
MergeRequest --> linter -->|comments| MergeRequest
MergeRequest --> unitTest[Unit Tests\npytest]
unitTest -->|comments| MergeRequest
MergeRequest --> intTest[Intergration tests\nHow much can we automate?]
intTest -->|comments| MergeRequest
MergeRequest --->|fail at tests if protected branch\nwhy waste human time?| codeReview
protected branch
versions on publishing
Look at this to manage the publish workflow logic
https://github.com/jedie/python-code-snippets/blob/master/CodeSnippets/setup_publish.py
This also uses twine to publish then which gives PGP siging support. Can we carry that though to PGP checking on download in poetry?
making the mono repo
walk you repo
#!/bin/sh
BASEDIR=$PWD
PKG=${PWD##*/}
DEPS=`grep -o '".*libs.*"' $PWD/poetry.lock | sed -e 's/"//g' | cut -d/ -f4`
mkdir -p $BASEDIR/dist/deps
for dep in $DEPS; do
cd ../../libs/$dep
rm -rf ./dist/*
poetry build
cp dist/*.whl $BASEDIR/dist/deps/.
cd $BASEDIR
done
cd $BASEDIR
poetry build
https://github.com/dermidgen/python-monorepo/blob/master/tools/ci-build.sh
Refs:
vscode mermaid plugin for markdown preview Ctrl-P then ext install bierner.markdown-mermaid