Hello,
I have recently tried to upload a package to PyPI with 2FA enabled and would like to share my experience.
More or less at random, I elected to use hatch
for this package. However, using hatch publish
gave mystifying errors (it doesn’t help that hatch
seems to use home-grown mechanisms to store credentials?).
I then switched to twine
, which gave me a slightly more helpful error message…
User XXX has two factor auth enabled, an API Token or Trusted Publisher must be used to upload in place of password.
… but only slightly, since it didn’t tell me how to actually use an API token (it also didn’t tell me how to create a token, but I figured that must be done from the PyPI account settings).
I then created an API token, and thought that I could try hatch publish
again, just by pasting the API token in the “credentials” prompt instead of my PyPI password (by the way why does it say “credentials” instead of a more explicit “password” or “token”?). Which didn’t work.
Switching to twine
again, I copied the snippet from the API token creation results into my .pypirc
and manually changed the required information such as the project name (a tedious operation, I have to say). I also noticed that the special username __token__
was used for that purpose instead of my regular username.
Now I can upload using twine upload -r my_project_name ...
, which works, but I have to remember to pass -r my_project_name
. The project name actually refers to an entry in .pypirc
that contains the project-specific API token, and pretends to be a separate repository entry…
However, I still don’t know how I could do all the above using hatch
instead (should I have gone with something else from the start?).
I would add that neither twine
nor hatch publish
ever mention 2FA in their respective command-line helps. The hatch
online docs revolve around classic password auth (I admit I haven’t checked the twine
online docs). This is unfortunate since 2FA is strongly recommended these days.
Side note: at first I had to create an account-wide API token, since the project I wanted to upload didn’t exist yet. Once I managed to create the project by uploading, I deleted the account-wide API token and created project-specific one. I then had to reconfigure .pypirc
a second time…
Side note #2: I just wanted to actually register the project so as to reserve the name. It is obviously not possible (why?), so I had to upload a version and immediately delete it…