A guide on how to distribute a Python CLI application, ensuring easy installation and shell autocompletion for users.
Packaging and Publishing to PyPI
Use setuptools in your setup.py file
from setuptools import setup, find_packages
with open("README.md", encoding="UTF-8") as file:
readme = file.read()
with open("requirements.txt", encoding="UTF-8") as file:
requirements = [line.strip() for line in file]
setup(
name="your-package-name",
version="your-package-version",
packages=find_packages(),
install_requires=[
requirements
],
entry_points={
"console_scripts": [
"your-command-name = your_package.module:function"
]
},
long_description=readme,
long_description_content_type="text/markdown",
)Replace your-package-name, your-package-version, your-command-name, your_package.module, and function with the appropriate values for your project.
Testing your package
In your virtual environment, you can install and test your package by running the following command:
You should be able to call your command in your virtual environment:
Publish your package to PyPI
- Install the required tools:
pip install setuptools wheel twine - Create a source distribution and a wheel distribution:
python setup.py sdist bdist_wheel - Upload the distributions to PyPI:
twine upload dist/*
Storing PyPi API Tokens
There are multiple ways to manage and securely store PyPI API tokens:
- Environment Variables: Store your API tokens as environment variables and reference them in your shell.
- .pypirc file: Store your tokens in a ~/.pypirc configuration file in your home directory. Beware of security risks as the file stores tokens in plaintext.
- keyring library: Use the keyring library to securely store API tokens.
The .pypirc file
A ~/.pypirc file might look like this:
[distutils]
index-servers =
pypi
PROJECT_NAME
[pypi]
username = __token__
password = API_TOKEN
[PROJECT_NAME]
repository = https://upload.pypi.org/legacy/
username = __token__
password = API_TOKEN
This file tells your packaging tools to authenticate against PyPi or other Python package indexes. Here:
distutilsis the main section, where you define your index servers.pypiis where you put your default PyPI credentials.PROJECT_NAMEis used to define per-project credentials.
Using Keyring
When using the keyring library, ensure that you have the necessary backend installed for your system. On Linux, keyring often uses the Secret Service daemon provided by GNOME or KWallet provided by KDE. For terminal-only environments or cloud servers, keyrings.alt may be used as a backend but it is less secure as it stores secrets in plaintext. On macOS, there is Keychain. And on Windows, Windows Credential Locker.
Then, you can use keyring to store your API token:
Unfortunately, there isn’t a builtin way to store different API tokens per project. Maybe this will change in the future, as PyPi is pushing everyone to enable 2FA, which requires the use of an API token to upload—and not just a password.
Shell Autocompletion
- If using
argcomplete, follow the instructions in the official documentation. - If using
click, follow the instructions in the official documentation.
Generate Completion Files for click
Save the script somewhere:
Bash
Source the file in
~/.bashrcZsh
Source the file in
~/.zshrcDon’t forget to make it executable.
I didn’t test it, but this might work for powershell:
Distributing with pipx
Instruct users to install and use pipx:
- Users should first install
pipx(if they haven’t already) usingpip:pip install --user pipx, or their system’s package manager. - They may need to add the pipx binary location to their PATH environment variable. For example, on Linux and macOS, they can add the following line to their shell profile file (
.bashrc,.zshrc, or similar):
export PATH="$HOME/.local/bin:$PATH"
- Users can then install your CLI application using
pipx:pipx install your-package-name.