Python packaging guideline: Local compilation to documentation
Packaging guide for beginners
The comprehensive guide from py-pkgs will be helpful in any case the following guidelines do not help.
To begin with packaging, you can either start by creating your own directories given below, or use the templates that poetry
(For managing package dependencies) or sphinx
(For documentation) could create for you.
Packaging brief for beginners
The comprehensive guide from py-pkgs will be helpful in case the following guidelines do not help.
To begin with packaging, you can either start by creating your own directories given below, or use the templates that poetry
(For managing package dependencies) or sphinx
(For documentation) could create for you.
Required modules/packages/formatting
We will start by looking at one section at a time. This section gives an overview of the process.
The repository format that worked reliably is given below.
package_repo
├── .readthedocs.yml
├── CHANGELOG.md
├── CONDUCT.md
├── CONTRIBUTING.md
├── docs
│ ├── changelog.md
│ ├── conduct.md
│ ├── conf.py
│ ├── contributing.md
│ ├── example.ipynb
│ ├── index.md
│ ├── make.bat
│ ├── Makefile
│ └── requirements.txt
├── LICENSE
├── README.md
├── pyproject.toml
├── poetry.lock
├── Makefile
├── package_repo
│ ├── __init__.py
│ ├── main.py
│ ├── moduleA
│ │ ├── __init__py
│ │ └── moduleA.py
│ ├── moduleB
│ │ ├── __init__py
│ │ └── moduleBfile.py
└── tests
├── __init__.py
└── test_package.py
Basic steps that reliably worked:
Poetry installation and MakeFile for package testing
- Put all the code inside the directory of the same name
- Remove all absolute path references, use
from .ModuleFile1 import Function11
to import a file from a specific file in the same directory. To import from level up, usefrom ..level_0.Module0File import Function01
. - Install poetry in a virtual environment as suggested by poetry. You will need
pipx
for this. Installpipx
using the methods indicated on the pipx webpage. Installpoetry
as indicated on poetry webpage. - Create .toml file by
poetry init
. Based on user input, it will create a basicpyproject.toml
file, which will look something like this. You can even copy the following and update the relevant information. Leave thebuild-system
the way it is.
Shown below is a pyproject.toml
file for FIREpyDAQ. FIREpyDAQ is Facilitated Interface for Recording Experiments (FIRE), a python based Data Acquisition (DAQ) system. Currently, it is geared towards devices that are traditionally used for data acquisition. More information can be found at firepydaq repository
[tool.poetry]
name = "firepydaq"
version = "0.1.0"
description = "A user-interface to read data during experiments"
authors = ["Dushyant Chaudhari <dushyant.chaudhari@ul.org>"]
license = "GNU General Public v3"
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.9,<3.13"
nidaqmx = "^1.0.0"
alicat = "0.6.2"
dash = "2.17.1"
dash-auth = "2.3.0"
dash-bootstrap-components = "1.6.0"
matplotlib = "3.8.4"
numpy = "1.26.0"
pandas = "2.2.2"
plotly = "5.22.0"
polars = "1.1.0"
pyarrow = "14.0.2"
pyqtgraph = "0.13.7"
pyserial = "3.5"
PySide6 = "6.7.2"
PyVISA = "1.14.1"
jsonschema = "4.23.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
-
Once the
.toml
file is read, you can callpoetry build
, which will create adist
folder that will have two files. The first is a wheel (.whl
) file and the other is an sdits (.tar.gz
) file. You can walk into thedist
file and runpip install ...whl
file. This will install this package locally. You can also share these wheels or dist files for installation of your package. -
To automate the poetry functions, a Makefile makes life easier. Makefile require installation of make, which needs to be further explored. Once make is available, create an empty
Makefile
and add commands as below. No you can simple runmake build
from your terminal/command prompt to automate building of the dist, creating poetry.lock, and installing the lock file in the virtual environment automatically created by poetry.
POETRY_OPTS ?=
POETRY ?= poetry $(POETRY_OPTS)
RUN_PYPKG_BIN = $(POETRY) run
##@ Building and Publishing
.PHONY: build
build: ## Runs a build
$(POETRY) build
$(POETRY) lock
$(POETRY) install
-
If you type
poetry env info
, it will list the virtual env you are working on. This virtual environment will have all the package dependencies installed so that you can run your package now in this environment. - To test a package in the poetry environment, you can install
pytest
that lets you run a specific set of files that begin or end withtest_
or_test
respectively inside thetests
directory. - You can create a
test_package.py
insidetests
, which could have various functions for testing. by defaultpytest
will only test functions that also has similar naming structure (test_
or_test
). - Before you can test, you will need to add a way for poetry to know that it needs to use pytest for testing the package. This can be done by calling the following two functions in cmd/terminal.
$ poetry add --group dev pytest
which will add the following lines in pyproject.toml
file
[tool.poetry.group.test.dependencies]
pytest = "^8.2.2"
- Once this is done, you can run
poetry run pytest -v
directly and it will tell you in terminal how manytest_
or_test
functions were tested. The success of running those functions is the passing criteria. Any failure is indicated in the terminal with the source of the error. The verbose option (-v
) will output the succes/failure of each collected test functions. - Alternatively, you can add a
test
PHONY
to the Makefile and runmake test
to initiate the testing.
##@ Testing
.PHONY: test
test: ## Runs tests
$(RUN_PYPKG_BIN) pytest -v \
tests/*.py
Documentation using sphinx
- Once you test that the package building works fine, you can move to documentation.
- Documentation will be compiled using sphinx, a commonly used resource for auto compilation. You can start by writing CONDUCT.md, CONTRIBUTING.md, CHANGELOG.md in the root folder. The references for each can be found in almost all packages.
- To begin building you will first need to add the following to poetry configuration.
$ poetry add --group dev myst-nb --python "^3.9"
$ poetry add --group dev sphinx-autoapi sphinx-rtd-theme
which will add the following to the pyproject.toml
file.
[tool.poetry.group.dev.dependencies]
myst-nb = {version = "^1.1.1", python = "^3.9"}
sphinx-autoapi = "^3.1.2"
sphinx-rtd-theme = "^2.0.0"
- Before we move on to building the documentation, we need a couple more things. First is the
docs
folder which containsindex.md
. Contents of index.md look something like below. Here, you will need to createchangelog.md
,contributing.md
, andconduct.md
that refer to the corresponding files in the root folder as how is done forREADME.md
below. The reason for this is that sphinx does not support relative references intoctree
.
```{include} ../README.md
```
```{toctree}
:maxdepth: 1
:hidden:
changelog.md
contributing.md
conduct.md
autoapi/index
```
- Next thing needed is
conf.py
,Makefile
, andmake.bat
files in the docs folder. These could have been created automatically if you used acookiecutter
. But to create them manually, the contents for each need to include the following (the basic minimum). - For
conf.py
, include the extensions required to build a sphinx documentation, the directory to build autoapis (by reading the code docstrings), and the theme. You may need to install the extensions, and the html theme manually if poetry cannot build the documentation for you and if you are required to do as a local copy directly. This is possibly due to some issues withMakefile
ormake.bat
(for windows).
extensions = [
"myst_nb",
"autoapi.extension",
"sphinx.ext.napoleon",
"sphinx.ext.viewcode",
]
autoapi_dirs = ["../src"] # location to parse for API reference
html_theme = "sphinx_rtd_theme"
- The Makefile has basic info as follows,
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = PACKAGE_NAME
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
and the make.bat has the following,
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=PACKAGE_NAME
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
- With these in place, you can compile the basic documentation by running
make html
command in thedocs
folder. This will create_build/html/index.html
, which you can open and see the locally compiled documentation.
Deploying on GitHub (version control) and GitHub Actions.
Stay tuned for another post.
Enjoy Reading This Article?
Here are some more articles you might like to read next: