4 Things Tutorials Don't Tell You About PyPI

Time to celebrate!

I published my first Python package to PyPI, Suite8080. It’s a suite of Intel 8080 Assembly cross-development tools. It’s in early development, misses some tools, and is rough around the edges. But it works, does something useful (if you’re into retrocomputing), and I’m having ridiculous amounts of fun with this hobby project.

Python Package Index (PyPI) website
The Python Package Index (PyPI) website.

The celebration is wearing out and I’m about to resume the work to complete and improve Suite8080, yet something still bugs me.

Although it’s well known PyPI is unforgiving for good reasons, the package publishing process is not as straightforward as the tutorials make it seem. I run into a few unexpected minor bumps none of the guides mention.

It’s not that the tutorials aren’t good, they are. I recommend the Real Python article on publishing a package to PyPI.

But the authors of these guides are so experienced, and probably so detached from the challenges beginners face, they may not be aware some issues and unknowns are worth addressing. So I thought I’d share my experience with PyPI while it’s still fresh, focusing on 4 things I haven’t seen discussed anywhere.


Relative URLs don’t work

Have you ever seen a PyPI entry with a great README.md but a missing screenshot replaced by the browser’s broken image icon? You can’t miss such entries as they stick out as sore thumbs.

I never figured why this happens and blamed sloppiness until I uploaded Suite8080 to Test PyPI for the very first time. Sure enough, although the screenshot in my README.md showed up nicely on GitHub, it was missing from the Test PyPI entry. A quick check of the Markdown source revealed PyPI doesn’t support relative URLs like ![My screenshot](screenshot.jpg) in README.md. Replacing the relative with an absolute URL starting with https://... fixed the issue. Since my README.md’s screenshot is hosted on GitHub, I can use a URL like https://raw.githubusercontent.com/username/projectname/master/image.jpg.

Neatness counts.


Test PyPI doesn’t purge packages

Once I realized the image link was broken on Test PyPI, I set out to re-upload the fixed package. I wanted to maintain the same version number for the new upload. Why? To keep future uploads in sync between Test PyPI and regular PyPI without changing the version number in the source. I wanted to minimize the differences to catch potential issues on Test PyPI first.

I knew PyPI doesn’t allow to remove versions but I read that Test PyPI is supposed to periodically delete uploaded packages, every 24 hours according to a source. However, the next day my previous upload was still there.

More research revealed Test PyPI nearly never purges packages. The purge seems to have happened only a handful of times over the history of the platform.

Never mind, I’ll let version numbers diverge until I can make them match again at the next minor release bump.


Indexing a new package takes 24 hours

The next step after making sure Suite8080 went live on regular PyPI and telling everyone and their brother was mashing the search box.

The project showed up on PyPI’s home page under the new releases and the link to the Suite8080 entry worked fine.

But searching for the exact name of the package returned nothing. I kept searching and poring over the result pages but ended up empty-handed. This seemed an issue as, until a project is indexed, tools such as shields.io that fetch data from PyPI don’t recognize the name and return an unknown package error.

It turns out poor PyPI needs some time to catch its breath and index new packages. The following day, Suite8080 became the first hit when searching for the exact name, as expected. So it takes the platform 24 hours to index new submissions.


You can delete Twine’s working folders

Building a project for distribution leaves around stuff in the source tree.

Twine stores its working files in the directories builddist, and projectname.egg-info. While I could leave them there as .gitignore takes care of skipping them, I wanted to remove the directories to maintain a cleaner source tree and make it easier to pick the correct archives from dist when uploading to PyPI.

After some experimentation, I figured I can safely remove the directories as running Twine has no side effects. Building the distribution from the same sources and metadata yields the same archives.

Popular posts from this blog

Using a Bluetooth Keyboard on Android

Lenovo Tab M8 HD Review

How to Add Code Syntax Highlighting to Blogger