Passwords, PyPI Uploads, twine
, and .pypirc
This document describes some pitfalls of interacting with PyPI.
Caveat
setuptools
is a 3rd party enhancement of the Python standard library's distutils
. It's hard for me to tell where on begins and the other ends, especially because setuptools
often operates by subclassing distutils
features. Some of the blame below aimed at setuptools
might more properly be directed at distutils
.
Uploading with setuptools
Uploading wheels to PyPI is a little awkward. The obvious way to do it is with this setuptools
command –
python setup.py bdist_wheel upload
There's already a shortcoming there, which is that one must create the wheel and upload it in the same step. There's no way to create the wheel, test it, and then upload it. That's just a quibble, though, since one can just create the wheel, test it, and then re-create it for the upload step. It's annoying if your wheel takes a long time to build. Fortunately, none of ours do.
setuptools
, Uploads and Passwords
Another annoyance is that setuptools
relies on ~/.pypirc
for authentication information, and it's a bit stupid about it.
If there's no authentication info present, it tries to upload your wheel without authentication, resulting in this:
Upload failed (401): You must be identified to edit package information
If there's partial authentication info present (say, a username without a password, which would be a convenient setup), rather than prompting you for a password, setuptools
just passes the password None
to distutils
which then fails with this –
File "/Users/vespa/miniconda2/lib/python2.7/distutils/command/upload.py", line 135, in upload_file
self.password)
TypeError: cannot concatenate 'str' and 'NoneType' objects
This is an easy problem to fix – just add the username and password to ~/.pypirc
. Now you have a much bigger problem, which is that your password is stored in cleartext on your hard drive.
setuptools
, Package Registration and Passwords
For some reason, setuptools
is smarter when running this command –
python setup.py register
If your password isn't in .pypirc
, it prompts you for it. Go figger.
Real Solution !#1 - keyring
KeyRing is a Python package that interacts with the OS keychain (Windows Credential Vault, Mac Keychain, etc.). This allows you to store your passwords securely and still access them with Python.
setuptools
can use keyring
if it's available. I haven't figured out how to set it up yet, though.
Real Solution !#2 - twine
Twine is a Python package that does one thing – upload stuff to PyPI. It allows you to upload your wheels independently of creating them, which is nice.
More importantly, it is smart enough to prompt you for a username/password if there isn't one present in .pypirc
.
Unfortunately, twine
doesn't use keyring
, so you have to manually enter your username/password when prompted.