I’ve uploaded a couple pypi packages in the past, but have never really kept them updated. Apparently, the updating process can be automated using Github Actions: https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/. (I’ll look at the next time.) For now, I’m going to use this tutorial (and revisit pypi-setup doco) to add a new package, regexify
, and update it so that new releases/versions are automatically posted to pypi.
I followed the guide here: https://packaging.python.org/tutorials/packaging-projects/, creating a README, LICENSE, and making sure the setup.py
file matched. (I usually start a new project by copy-pasting my previous setup.py
and updating as needed.) Make sure pip, setuptools, and wheel are updated:
pip install --upgrade setuptools wheel python -m pip install --upgrade pip
And then build the distribution:
python setup.py sdist bdist_wheel
I already had a PyPI account, so going under ‘Account Settings’ > ‘API tokens’ > ‘Add API token’. Please note that you will also need a ‘test pypi’ account with a separate API token to ‘test’ the upload process. (In other words, register and get API tokens from both https://test.pypi.org and https://pypi.org.)

For a new project, the scope will need to be ‘Entire account’, though I’m naming the token after the package I’m uploading — hopefully I can reduce scope after the project exists on PyPI.
Copying the token and adding it to my .pypirc
file, located in the $HOME
directory (just type $home
in bash/powershell). Mine looks like this (well, almost):

I’ll use twine
to upload, and will test first on testpypi
. Also, not really sure if it’s best to install under my virtual environment or not. I’ll keep using the venv.
pip install --upgrade twine
And then upload:
twine upload --repository testpypi dist/*
I initially ran into an error saying the my markdown README file didn’t count as valid reStructuredText, which it doesn’t.
400 The description failed to render in the default format of reStructuredText. See https://test.pypi.org/help/#description-content-type for more information.
I liked a solution from Stackoverflow (user: Jakub Jirutka), reproduced below, although the simpler approach is to just specify the setup
option, long_description_content_type='text/markdown'
.
from setuptools import setup try: from pypandoc import convert read_md = lambda f: convert(f, 'rst') except ImportError: print('warning: pypandoc module not found, could not convert Markdown to RST') read_md = lambda f: open(f, 'r').read() setup( # name, version, ... long_description=read_md('README.md'), install_requires=[] )
Rebuilding with python setup.py sdist bdist_wheel
and twine upload
worked.
Once this is successful, assuming that the pypi API token is correctly added to the .pypirc
file, one more call to twine will upload to PyPI.
twine upload --verbose --repository pypi dist/*
The output points me to the PyPI URL where I can check it out: https://pypi.org/project/regexify/0.1.1/.
Now, I can use pip install regexify
to try it out!