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:
distutils
is the main section, where you define your index servers.pypi
is where you put your default PyPI credentials.PROJECT_NAME
is 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
~/.bashrc
Zsh
Source the file in
~/.zshrc
Don’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
.