You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Recommended workflow for switching between multiple API tokens? #496
changed the title [-]Recommended workflow for using multiple API tokens?[/-][+]Recommended workflow for switching between multiple API tokens?[/+]on Sep 11, 2019
$ twine upload --repository example-pkg dist/*
InvalidConfiguration: Missing 'example-pkg' section from the configuration file
or not a complete URL in --repository-url.
Maybe you have a out-dated '~/.pypirc' format?
more info: https://docs.python.org/distutils/packageindex.html#pypirc
A quick search didn't uncover any issues on Warehouse, which surprised me. It seems like a quick addition to the relevant Warehouse docs, but seems to add to the case for improving Twine's handling of tokens.
While this works, I agree with @sigmavirus24 that it's a bit of a hack. I think it's probably worthwhile for us to think of a new and better way to do this in the .pypirc file (and maybe standardize the format while we're at it?)
Thanks, @di. I wondered how much freedom we might have with the .pypirc format. I like how this removes the need for repository = https://upload.pypi.org/legacy/ in the config for project-scoped tokens.
I could be wrong, but I think these extra fields/sections would be ignored by any tool that doesn't know about them, so it should be fully backwards-compatible.
That keeps us from proliferating sections into the file, keeps the implementation simple, and is farily explicit without trying to hack around things. Then we can select the tokens out of there as necessary without doing "repository" based nonsense. Getting this to work with Keyring will be harder, as the discussion Brian linked indicates
From pypa/packaging.python.org#297, it seems like the ideal scenario is that tokens are not stored in .pypirc, but rather in keyring. Does that influence the choice of format?
I think you're always going to have people who would prefer not to use keyring. And we'd have to go through a lengthy deprecation period to kill that off which isn't worth the effort frankly.
Gotcha, so with that example, if the user just wanted to specify repo-wide tokens (which is probably the most common use case? maybe?) they'd have to write a minimum of:
The fact that we don't know what the most common use-case is suggests that we don't know enough to continue pushing forward on making the right choice
As of right now, 60% of PyPI users who own/maintain at least package only have one package:
warehouse=> select count(*) from (select roles.user_id, count(roles.project_id) as
count from roles group by user_id) as projects;
count
--------
103550
(1 row)
warehouse=> select count(*) from (select roles.user_id, count(roles.project_id) as
count from roles group by user_id) as projects where projects.count = 1;
count
-------
62803
(1 row)
Related (I think): I just put up a draft PR that documents the current spec of .pypirc: pypa/packaging.python.org#734.
Also, we're talking a lot about .pypirc, but I'm curious how this would manifest in configuration via the command line and/or environment variables. For example, does this imply --token and TWINE_TOKEN? It seems friendlier for those to be aligned.
I'm wondering if it might be simpler to keep the current convention, but mitigate the hack by defaulting username to __token__, as suggested in #561.
I think that would also require fewer updates to the docs in Twine, PPUG, and Warehouse.
As of right now, 60% of PyPI users who own/maintain at least package only have one package:
Is there a way to tell what % of that 60% use tokens at all?
Here's the point: If we go with token= then we're implicitly endorsing 1 global token that everyone should be using and thus we're going to calcify that use-case. Is the goal of project-scoped tokens not to (beyond enabling CI) to also encourage keeping tokens scoped appropriately to projects?
We should be meeting folks where they are today, certainly, but we should also be striving to push the community forward with the gentlest nudges we can think of.
I'd like us to imagine a world where using password in .pypirc is deprecated or discouraged, and I think that overloading password with the token value would make that hard or impossible.
I think that a default username of __token__ might produce some confusing behavior in some edge cases, for example consider the following:
Twine now has no way to tell the user their username is "missing" because it happily falls back on the default of __token__, which fails authentication, even though the user has included the correct username/password (unless we want to start warning the user every time Twine uses the default, which I think would get annoying for users who legitimately want to use tokens)
Using token over password allows the user to explicitly tell us "I expect to use tokens" which allows us to potentially do some preflight checking of this value (i.e. whether it's a valid token). Otherwise, we'd have to implicitly infer this through how the user is using the username field.
Having a clear delineation between what is a token and what is a password in configuration will help provide more context to whatever mechanism implements Pluggable credential manager framework proposal [PoC included] #362, which would allow an authentication provider to provide a different value based on what's being requested. E.g.:
$ twine upload -r <my-package> dist/*.tar.gz --verbose
INFO Using configuration from /home/shon/.pypirc
ERROR InvalidConfiguration: Missing '<my-package>' section from ~/.pypirc.
More info: https://packaging.python.org/specifications/pypirc/
What worked
Rename [<my-package>] to [pypi]
twine upload -r <my-package> dist/*.tar.gz
But then obviously I can't use this for other packages.
Chiming in briefly to inquire if there's appetite for removing the need for the entire [distutils] section and index-servers keys. (I slammed face-first into this issue today.)
Is there still a benefit to preserving usage of this indirection, vs setting sections and looking for those? (Potentially replace configparser.RawConfigParser which is a legacy form of configparser.ConfigParser )
Activity
[-]Recommended workflow for using multiple API tokens?[/-][+]Recommended workflow for switching between multiple API tokens?[/+]sigmavirus24 commentedon Sep 12, 2019
That looks accurate. I'd say that it's a hack but it's the first thing I thought of when I saw your question.
It would probably be good to have another way of managing these though instead of forcing folks to use
--repositorynlhkabu commentedon Sep 13, 2019
Ok, thanks @sigmavirus24. I will go ahead and get these instructions merged into Warehouse.
bhrutledge commentedon Oct 3, 2019
@sigmavirus24 and @nlhkabu is it okay to close this? And/or should we open an issue for improving the UX for using Twine with API tokens?
bhrutledge commentedon Jan 26, 2020
FYI @sigmavirus24 and @nlhkabu (and @di for good measure):
After trying this out for myself, I think the instructions might not be sufficient. Given this
~/.pypirc:I get this output:
It works if add I this to the top of
~/.pypirc:I discovered that
twine.utils.get_configonly uses values for definedindex-servers, which defaults to["pypi", "testpypi"].twine/twine/utils.py
Lines 78 to 85 in 330c0a2
A quick search didn't uncover any issues on Warehouse, which surprised me. It seems like a quick addition to the relevant Warehouse docs, but seems to add to the case for improving Twine's handling of tokens.
Fix example .pypirc for project tokens
bhrutledge commentedon Jan 26, 2020
Related: #565 - Not obvious how to use multiple project API tokens with keyring
Fix example .pypirc for project tokens (#7305)
di commentedon Jan 26, 2020
While this works, I agree with @sigmavirus24 that it's a bit of a hack. I think it's probably worthwhile for us to think of a new and better way to do this in the
.pypircfile (and maybe standardize the format while we're at it?)Maybe something like this for repo-wide tokens:
And this for project-specific tokens:
bhrutledge commentedon Jan 27, 2020
Thanks, @di. I wondered how much freedom we might have with the
.pypircformat. I like how this removes the need forrepository = https://upload.pypi.org/legacy/in the config for project-scoped tokens.FYI, there's an evolving discussion that started at pypa/packaging.python.org#297 (comment), where @jaraco and @takluyver have proposed some ideas on how to make this work with keyring and flit.
di commentedon Jan 27, 2020
I could be wrong, but I think these extra fields/sections would be ignored by any tool that doesn't know about them, so it should be fully backwards-compatible.
bhrutledge commentedon May 28, 2020
Marked this and #565 as blocked until the discussion started at pypa/packaging.python.org#297 (comment) is resolved.
sigmavirus24 commentedon May 28, 2020
The other thing to keep in mind is that the ini format is fairly flexible and projects like pytest and flake8 are able to do things like:
option = something: value something-else: another-valueSo we could keep this super simple and have a:
tokens = *: pypi<general token> twine: pypi<project-token> ...That keeps us from proliferating sections into the file, keeps the implementation simple, and is farily explicit without trying to hack around things. Then we can select the tokens out of there as necessary without doing "repository" based nonsense. Getting this to work with Keyring will be harder, as the discussion Brian linked indicates
3 remaining items
bhrutledge commentedon May 29, 2020
From pypa/packaging.python.org#297, it seems like the ideal scenario is that tokens are not stored in
.pypirc, but rather inkeyring. Does that influence the choice of format?sigmavirus24 commentedon May 29, 2020
I think you're always going to have people who would prefer not to use keyring. And we'd have to go through a lengthy deprecation period to kill that off which isn't worth the effort frankly.
The fact that we don't know what the most common use-case is suggests that we don't know enough to continue pushing forward on making the right choice
di commentedon May 29, 2020
As of right now, 60% of PyPI users who own/maintain at least package only have one package:
bhrutledge commentedon May 30, 2020
Related (I think): I just put up a draft PR that documents the current spec of
.pypirc: pypa/packaging.python.org#734.Also, we're talking a lot about
.pypirc, but I'm curious how this would manifest in configuration via the command line and/or environment variables. For example, does this imply--tokenandTWINE_TOKEN? It seems friendlier for those to be aligned.I'm wondering if it might be simpler to keep the current convention, but mitigate the hack by defaulting
usernameto__token__, as suggested in #561.I think that would also require fewer updates to the docs in Twine, PPUG, and Warehouse.
sigmavirus24 commentedon May 30, 2020
Is there a way to tell what % of that 60% use tokens at all?
Here's the point: If we go with
token=then we're implicitly endorsing 1 global token that everyone should be using and thus we're going to calcify that use-case. Is the goal of project-scoped tokens not to (beyond enabling CI) to also encourage keeping tokens scoped appropriately to projects?We should be meeting folks where they are today, certainly, but we should also be striving to push the community forward with the gentlest nudges we can think of.
bhrutledge commentedon May 30, 2020
@sigmavirus24 I think @di's original suggestion handles project-scoped tokens via additional sections that inherit from the "base" section:
Another idea:
That said, I'd still like to consider sticking with the current
username/passwordhack, such that Twine's default configuration becomes:which I think leans more towards something like this:
bhrutledge commentedon May 30, 2020
Building on my last suggestion, combined with my second proposal in #565 and pypa/packaging.python.org#297 (comment), I think this would allow CLI commands like:
Aside: looking over those other issues makes me wonder if this is conversation should be moved to https://discuss.python.org/c/packaging/.
di commentedon Jun 1, 2020
A few things on the password/token "hack":
I'd like us to imagine a world where using
passwordin.pypircis deprecated or discouraged, and I think that overloadingpasswordwith the token value would make that hard or impossible.I think that a default
usernameof__token__might produce some confusing behavior in some edge cases, for example consider the following:Twine now has no way to tell the user their username is "missing" because it happily falls back on the default of
__token__, which fails authentication, even though the user has included the correct username/password (unless we want to start warning the user every time Twine uses the default, which I think would get annoying for users who legitimately want to use tokens)Using
tokenoverpasswordallows the user to explicitly tell us "I expect to use tokens" which allows us to potentially do some preflight checking of this value (i.e. whether it's a valid token). Otherwise, we'd have to implicitly infer this through how the user is using theusernamefield.Having a clear delineation between what is a token and what is a password in configuration will help provide more context to whatever mechanism implements Pluggable credential manager framework proposal [PoC included] #362, which would allow an authentication provider to provide a different value based on what's being requested. E.g.:
(where we can probably just consider
keyringthe default password/token provider, but I'm including it here just as an example)shon commentedon Jul 27, 2022
I faced the similar issue today
To reproduce
OS: Ubuntu 22.04
Python: 3.10.4
Twine: 4.0.1
Twine command
What worked
[<my-package>]to[pypi]-r <my-package>dist/*.tar.gzBut then obviously I can't use this for other packages.
bhrutledge commentedon Jul 27, 2022
@shon Can you try adding
<my-package>toindex-serversin your.pypirc?I think that will allow you to run:
shon commentedon Jul 27, 2022
Thanks @bhrutledge that worked!
Wasn't very intuitive to me that my-package should be mentioned
index-servers.bhrutledge commentedon Jul 27, 2022
@shon Me neither, which led to the discussion starting at #496 (comment).
kentbull commentedon Mar 6, 2023
Agree with @shon. I like @bhrutledge and @di's comments on a path forward.
Doondondon commentedon Nov 4, 2023
miketheman commentedon Dec 21, 2023
Chiming in briefly to inquire if there's appetite for removing the need for the entire
[distutils]section andindex-serverskeys. (I slammed face-first into this issue today.)distutilshas been removed from Python as of 3.12+, and twine hasn't useddistutilsdirectly for over a decade.Is there still a benefit to preserving usage of this indirection, vs setting sections and looking for those? (Potentially replace
configparser.RawConfigParserwhich is a legacy form ofconfigparser.ConfigParser)