This is an example PyPI (Python Package Index) package set up with automated tests and package publishing workflow using GitHub Actions CI/CD. It is made primarily for GitHub + VS Code (Windows / Mac / Linux) users who are about to write and publish their first PyPI package. The package could serve as a starter / boilerplate / demo and the tutorial could give you a quick and concise explaination to solve some small but annoying problems you might encounter, such as package / module name confusion, and VS Code test configuration issues.
(Click the above button to use this example package as a template for your new GitHub repo, this will initialize a new repository and my commits will not be in your git history)
(If you do not use GitHub, you can download the archive of the example package)
Many use a same package and module name, you could definitely do that. But this example package and its module's names are different: example_pypi_package
and examplepy
.
Open example_pypi_package
folder with Visual Studio Code, Ctrl + Shift + F (Windows / Linux) or Cmd + Shift + F (MacOS) to find all occurrences of both names and replace them with your package and module's names. Also remember to change the name of the folder src/examplepy.
Simply and very roughly speaking, package name is used in pip install <PACKAGENAME>
and module name is used in import <MODULENAME>
. Both names should consist of lowercase basic letters (a-z). They may have underscores (_
) if you really need them. Hyphen-minus (-
) should not be used.
You'll also need to make sure the URL "https://pypi.org/project/example-pypi-package/" (replace example-pypi-package
by your package name, with all _
becoming -
) is not occupied.
Make necessary changes in setup.py.
The package's version number __version__
is in src/examplepy/__init__.py. You may want to change that.
The example package is designed to be compatible with Python 3.6, 3.7, 3.8, 3.9, and will be tested against these versions. If you need to change the version range, you should change:
classifiers
, python_requires
in setup.pyenvlist
in tox.inimatrix: python:
in .github/workflows/test.ymlIf you plan to upload to TestPyPI which is a playground of PyPI for testing purpose, change twine upload --repository pypi dist/*
to twine upload --repository testpypi dist/*
in the file .github/workflows/release.yml.
pip is a Python package manager. You already have pip if you use Python 3.4 and later version which include it by default. Read this to know how to check whether pip is installed. Read this if you need to install it.
Visual Studio Code is the most popular code editor today, our example package is configured to work with VS Code.
Install VS Code extension "Python".
"Python" VS Code extension will suggest you install pylint. Also, the example package is configured to use pytest with VS Code + Python extensions, so, install pylint and pytest:
pip install pylint pytest
(It's likely you will be prompted to install them, if that's the case, you don't need to type and execute the command)
vscode.env's content is now PYTHONPATH=/;src/;${PYTHONPATH}
which is good for Windows. If you use Linux or MacOS, you need to change it to PYTHONPATH=/:src/:${PYTHONPATH}
(replacing ;
with :
). If the PATH is not properly set, you'll see linting errors in test files and pytest won't be able to run tests/test_*.py files correctly.
Close and reopen VS Code. You can now click the lab flask icon in the left menu and run all tests there, with pytest. pytest seems better than the standard unittest framework, it supports unittest
thus you can keep using import unittest
in your test files.
The example package also has a .editorconfig file. You may install VS Code extension "EditorConfig for VS Code" that uses the file. With current configuration, the EditorConfig tool can automatically use spaces (4 spaces for .py, 2 for others) for indentation, set UTF-8
encoding, LF
end of lines, trim trailing whitespaces in non Markdown files, etc.
In VS Code, you can go to File -> Preferences -> Settings, type "Python Formatting Provider" in the search box, and choose one of the three Python code formatting tools (autopep8, black and yapf), you'll be prompted to install it. The shortcuts for formatting of a code file are Shift + Alt + F (Windows); Shift + Option (Alt) + F (MacOS); Ctrl + Shift + I (Linux).
In src/examplepy/ (examplepy
should have been replaced by your module name) folder, rename module1.py and write your code in it. Add more module .py files if you need to.
In tests/ folder, rename test_module1.py (to test_*.py) and write your unit test code (with unittest) in it. Add more test_*.py files if you need to.
If you add more files to the root directory (example_pypi_package/), you'll need to add your file to check-manifest --ignore
list in tox.ini.
Register an account on PyPI, go to Account settings § API tokens, "Add API token". The PyPI token only appears once, copy it somewhere. If you missed it, delete the old and add a new token.
(Register a TestPyPI account if you are uploading to TestPyPI)
On the page of your newly created or existing GitHub repo, click Settings -> Secrets -> New repository secret, the Name should be PYPI_API_TOKEN
and the Value should be your PyPI token (which starts with pypi-
).
The example package has automated tests and upload (publishing) already set up with GitHub Actions:
git push
or a pull request is submitted on your master
or main
branch, the package is automatically tested against the desired Python versions with GitHub Actions.After your package is published on PyPI, go to https://pypi.org/project/example-pypi-package/ (_
becomes -
). Copy the command on the page, execute it to download and install your package from PyPI. (or test.pypi.org if you use that)
If you want to modify the description / README of your package on pypi.org, you have to publish a new version.
Btw, if you want to publish TypeScript (JavaScript) package to the npm registry, go to Example TypeScript Package ready to be published on npm for 2021.