Closed wahuneke closed 1 year ago
Do you have private repositories present in your pyproject.toml
file?
I think you are affected by the issue that is fixed by #1892. The fix will be available in the next bug fix release.
I was affected by something similar on the latest release (1.0.5), but I'm not sure if it's entirely the same.
The keyring will be hit for private repos if there is an auth.toml
with only the username set, even if credentials are provided via environment variables.
I believe the relevant code is here. In this case, auth
will be truthy, causing the keyring path to be taken.
In our case, the "fix" was to remove any leftover auth.toml
files in the environment. Manually uninstalling keyring had the same effect.
I was wondering your thoughts on adding a config variable that would prevent any keyring hits altogether (by e.g. unconditionally marking the keyring as unavailable). This would have largely the same effect as @wahuneke's workaround, but might be a bit cleaner for CI pipelines and such.
+1 to this. I am facing similar issue while integrating poetry with Jenkins. Even though private repo credentials were provided via environment variables, poetry still tries to look into keyring for credentials.
+1 running into this issue while working over ssh
fwiw, I came across this issue and agree with the concerns mentioned above.
But fwiw, I came here due to a issue with my distro that shows a dependency mismatch on keyring. keyring==18 is required (circa 2019), where as my distro has keyring-21.2 available, not sure without looking on the compatibility issues, but thought I'd mention if in case that can be relaxed....
$ poetry init
Traceback (most recent call last):
File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 583, in _build_master
ws.require(__requires__)
File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 900, in require
needed = self.resolve(parse_requirements(requirements))
File "/usr/lib/python3.8/site-packages/pkg_resources/__init__.py", line 791, in resolve
raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (keyring 21.2.1 (/usr/lib/python3.8/site-packages), Requirement.parse('keyring==18.*,>=18.0.0'), {'poetry'})
I'm seeing this issue in poetry 1.1.6
My setup: MacOS Mojave 10.14.6 localhost private pypiserver with authentication required for upload only
[[tool.poetry.source]]
name = "foo"
url = "http://localhost/simple/"
secondary = true
$ poetry config --list
cache-dir = "..."
experimental.new-installer = true
installer.parallel = true
repositories.foo.url = "http://localhost"
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.path = "{cache-dir}/virtualenvs"
$ cat auth.toml
[http-basic]
[http-basic.foo]
username = "kakarukeys"
The commands that poetry asked for keyring access:
poetry add lxml
??? why? it should get the package from the official PyPI
poetry run python --version
this makes no sense either.
if you need the installation scripts for the local private pypi let me know
+1 this
Poetry searches for a package in all package sources by default.
Additionally you might want to add the publishing repository with a different name, if the source uses the same name authenticator will load the credentials.
Poetry 1.2 now hits the keyring for most operations (add, update, install, self update, etc) rendering it unusable for me. I can "fix" the problem by exporting PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
but it would be much nicer if poetry just didn't hit the keyring at all if it wasn't needed.
I tried poetry for the first time today.
This command will guide you through creating your pyproject.toml config.
Package name [herpderp]:
Version [0.1.0]:
Description []:
Author [txtsd <herp@derp.com>, n to skip]:
License []: GPL-3.0-only
Compatible Python versions [^3.10]:
Would you like to define your main dependencies interactively? (yes/no) [yes] yes
You can specify a package in the following forms:
- A single name (requests): this will search for matches on PyPI
- A name and a constraint (requests@^2.23.0)
- A git url (git+https://github.com/python-poetry/poetry.git)
- A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
- A file path (../my-package/my-package.whl)
- A directory (../my-package/)
- A url (https://example.com/packages/my-package-0.1.0.tar.gz)
Package to add or search for (leave blank to skip): requests
Found 20 packages matching requests
Showing the first 10 matches
Enter package # to add, or the complete package name if it is not listed []:
[ 0] requests
[ 1] requests5
[ 2] requests3
[ 3] requests2
[ 4] pycopy-requests
[ 5] requests-middleware
[ 6] grasspy-requests
[ 7] requests-kerberos
[ 8] fed-requests
[ 9] requests-httpsproxy
[10]
> 1
Enter the version constraint to require (or leave blank to use the latest version):
Failed to open keyring: org.freedesktop.DBus.Error.ServiceUnknown: The name :1.146 was not provided by any .service files.
What a horrible experience. If there isn't a keyring, assume it doesn't exist and continue. Why hard fail at this stage? It's not even like I don't have a keyring. I use KeePassXC's freedesktop.org Secrets integration. It works fine system-wide.
@txtsd Keyring support is a new feature, and this is a complex interaction across the matrix of possible platforms, configurations, versions, and backends that a user may invoke Poetry in. Many of these sharp edges simply haven't been filed off because of how large that matrix is and how dependent on external factors keychain interactions are.
MRs improving the authentication experience or docs are welcome -- we're going to have to gradually file down these rough edges as keychain support matures.
Had the same issue. Had to change the keyring package config to point to the keyring.backends.SecretService.Keyring
backend. For me the keyring package was trying to use kwallet
, but I'm using Gnome not KDE.
OS = Arch Linux DE = Gnome
Okay, I created this file ~/.config/python_keyring/keyringrc.cfg
and populated it with
[backend]
default-keyring=keyring.backends.SecretService.Keyring
Then I unset PYTHON_KEYRING_BACKEND
and ran poetry init
:
λ poetry init
This command will guide you through creating your pyproject.toml config.
Package name [test]:
Version [0.1.0]:
Description []:
Author [txtsd <herp@derp.com>, n to skip]:
License []:
Compatible Python versions [^3.10]:
Would you like to define your main dependencies interactively? (yes/no) [yes]
You can specify a package in the following forms:
- A single name (requests): this will search for matches on PyPI
- A name and a constraint (requests@^2.23.0)
- A git url (git+https://github.com/python-poetry/poetry.git)
- A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
- A file path (../my-package/my-package.whl)
- A directory (../my-package/)
- A url (https://example.com/packages/my-package-0.1.0.tar.gz)
Package to add or search for (leave blank to skip): lxml
Found 20 packages matching lxml
Showing the first 10 matches
Enter package # to add, or the complete package name if it is not listed []:
[ 0] lxml
[ 1] lxml-stubs
[ 2] zsi-lxml
[ 3] lxml-wrapper
[ 4] readability-lxml
[ 5] lxml2dict
[ 6] suds-lxml
[ 7] json-lxml
[ 8] lxml-asserts
[ 9] gocept.lxml
[10]
> 0
Enter the version constraint to require (or leave blank to use the latest version):
Empty module name
Different error now.
There's some busted keyring behavior with your particular backends that seem to
poetry init
was not made robust against keyring errors as an oversight)Some more insight into your system (what backend should be available, OS version, package versions), etc would be helpful for those that attempt to address yours/similar issues @txtsd.
In the meantime, you can revert to 1.1-style writing to disk using the keyring.backends.null.Keyring
backend, of course.
@neersighted I use Arch Linux
λ pip freeze | grep poetry
poetry==1.2.0
poetry-core==1.1.0
poetry-plugin-export==1.0.6
I set the config to use keyring.backends.null.Keyring
for now. Thanks!
Happened to me today for the first time. I used Poetry until last month without any issues, but today I saw same error.
export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
seems to fix the issue.
I'm seeing the same error on Windows with libsecret installed:
• Installing urllib3 (1.26.12): Failed
Error
g-dbus-error-quark: The name org.freedesktop.secrets is unknown (2)
I wanted to add my experience with this issue. We are running our CI on Github self-hosted runners (Ubuntu 20.04) and instead of getting an error, Poetry would just hang when running poetry install
. After some digging I found that it was stalling on the collection.unlock()
call in the keyring
library, presumably because the gnome-keyring-daemon
was not launching without a user login.
The PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
fix worked for me but it cost me a lot of time troubleshooting this.
My suggestion is to make the keychain
backend an opt-in feature.
I have the same problem on WSL2:
1 /usr/lib/python3.10/site-packages/keyring/core.py:72 in get_credential
return get_keyring().get_credential(service_name, username)
Error
g-spawn-exit-error-quark: Error spawning command line “dbus-launch --autolaunch=93716890c157416eacbb2d8801a1e4f6 --binary-syntax --close-stderr”: Child process exited with code 1 (1)
disabling the keyring fixes the problem. I think this feature should be opt-in as suggested by @blakjak44
I get the following on Ubuntu Mint 20.04.5 LTS
and Python 3.10.7
, using Poetry 1.2.1
, when I remotely SSH to the machine.
It seems that if I do an RDP session to the GUI of this machine and unlock my keyring which is empty for what its worth, then I don't get this error. The fix mentioned about disabling it with PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
also worked as well.
clab_arista$ poetry install
Installing dependencies from lock file
Package operations: 8 installs, 0 updates, 0 removals
• Installing markupsafe (2.1.1): Failed
KeyringLocked
Failed to unlock the collection!
at ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/keyring/backends/SecretService.py:67 in get_preferred_collection
63│ raise InitError("Failed to create the collection: %s." % e)
64│ if collection.is_locked():
65│ collection.unlock()
66│ if collection.is_locked(): # User dismissed the prompt
→ 67│ raise KeyringLocked("Failed to unlock the collection!")
68│ return collection
69│
70│ def unlock(self, item):
71│ if hasattr(item, 'unlock'):
Poetry searches for a package in all package sources by default.
@abn: But it happens even with no configured package sources, i.e. when only going against PyPI
@txtsd Keyring support is a new feature, and this is a complex interaction across the matrix of possible platforms, configurations, versions, and backends that a user may invoke Poetry in. Many of these sharp edges simply haven't been filed off because of how large that matrix is and how dependent on external factors keychain interactions are.
MRs improving the authentication experience or docs are welcome -- we're going to have to gradually file down these rough edges as keychain support matures.
@neersighted: If that's the case, it shouldn't be enabled by default IMO. For me add
just hanged for a while with no feedback on why it was hanging until the keyring password prompt appeared. I didn't want it to access the keyring, so I canceled that, and then the add was aborted. This is a pretty bad experience out of the box. poetry add --help
doesn't mention anything about the keyring either, so I had to search and find this issue to figure out how to disable it. I found https://python-poetry.org/docs/repositories/ which mentions keyrings before this issue, but that doesn't mention disabling it either.
I just tried upgrading to poetry 1.2.x, did poetry install
and got thousands of Failed to create the collection: Prompt dismissed..
errors.
All other commands are broken as well even self update
is broken without the mitigation.
Going back to 1.1.x until this is fixed. I don't want to tell all my developers that hey have to mess with PYTHON_KEYRING_BACKEND
just to be able to use the most basic features.
And this while i was really looking to move to 1.2
keyring --disable
solved the issue for me
keyring --disable
solved the issue for me
It just changed to a new error with that.
This is happening on Poetry 1.2.2 for me, the following fixes the issue as mentioned in #5250:
export PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring
I'm running into this too. I see that there is already a fallback if the returned credential is None, so maybe this is just a matter of catching KeyringLocked
and returning the default too?
A better option would probably be for Authenticator
to try the request without credentials, only trying to obtain credentials if they are required (for example HTTP 401). This is the way most clients work, including web browsers. Unlocking the keyring for every request is definitely the wrong behavior.
edit: I'm happy to contribute a fix, but this requires a maintainer to pick between the options above. Or should I open 2 PRs?
I had the same problem on Fedora 37 beta. Poetry had been working until I updated to latest. I was trying to do poetry add
. I was having a problem where my lock file wasn't updating with the toml requirements. So I tried poetry add
and was getting the error mentioned here.
@croqaz suggestion fixed it for me.
export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
I'm getting this issue when ssh session into a Windows 11 machine. poetry 1.2.2
poetry install -vvv Installing dependencies from lock file
Finding the necessary packages for the current system
Package operations: 26 installs, 1 update, 0 removals
• Installing shiboken6 (6.4.0.1) [keyring.backend] Loading KWallet [keyring.backend] Loading SecretService [keyring.backend] Loading Windows [keyring.backend] Loading chainer [keyring.backend] Loading libsecret [keyring.backend] Loading macOS
Stack trace:
2 C:\Program Files\Python310\lib\site-packages\win32ctypes\pywin32\pywintypes.py:35 in pywin32error 33│ def pywin32error(): 34│ try: → 35│ yield 36│ except WindowsError as exception: 37│ raise error(exception.winerror, exception.function, exception.strerror)
1 C:\Program Files\Python310\lib\site-packages\win32ctypes\pywin32\win32cred.py:70 in CredRead 68│ else: 69│ pcreds = _authentication.PCREDENTIAL() → 70│ _authentication._CredRead( 71│ TargetName, Type, flag, _common.byreference(pcreds)) 72│ try:
OSError
[WinError 1312] A specified logon session does not exist. It may already have been terminated.
at C:\Program Files\Python310\lib\site-packages\win32ctypes\core\ctypes_util.py:53 in check_zero 49│ 50│ def check_zero_factory(function_name=None): 51│ def check_zero(result, function, arguments, *args): 52│ if result == 0: → 53│ raise make_error(function, function_name) 54│ return result 55│ return check_zero 56│ 57│
The following error occurred when trying to handle this error:
Stack trace:
21 C:\Program Files\Python310\lib\site-packages\poetry\installation\executor.py:261 in _execute_operation 259│ 260│ try: → 261│ result = self._do_execute_operation(operation) 262│ except EnvCommandError as e: 263│ if e.e.returncode == -2:
20 C:\Program Files\Python310\lib\site-packages\poetry\installation\executor.py:334 in _do_execute_operation 332│ return 0 333│ → 334│ result: int = getattr(self, f"execute{method}")(operation) 335│ 336│ if result != 0:
19 C:\Program Files\Python310\lib\site-packages\poetry\installation\executor.py:454 in _execute_install 452│ 453│ def _execute_install(self, operation: Install | Update) -> int: → 454│ status_code = self._install(operation) 455│ 456│ self._save_url_reference(operation)
18 C:\Program Files\Python310\lib\site-packages\poetry\installation\executor.py:488 in _install 486│ archive = self._download_link(operation, Link(package.source_url)) 487│ else: → 488│ archive = self._download(operation) 489│ 490│ operation_message = self.get_operation_message(operation)
17 C:\Program Files\Python310\lib\site-packages\poetry\installation\executor.py:633 in _download 631│ 632│ def _download(self, operation: Install | Update) -> Path: → 633│ link = self._chooser.choose_for(operation.package) 634│ 635│ if link.yanked:
16 C:\Program Files\Python310\lib\site-packages\poetry\installation\chooser.py:77 in choose_for 75│ """ 76│ links = [] → 77│ for link in self._get_links(package): 78│ if link.is_wheel: 79│ if not self._no_binary_policy.allows(package.name):
15 C:\Program Files\Python310\lib\site-packages\poetry\installation\chooser.py:119 in _get_links 117│ else: 118│ repository = self._pool.repository("pypi") → 119│ links = repository.find_links_for_package(package) 120│ 121│ hashes = [f["hash"] for f in package.files]
14 C:\Program Files\Python310\lib\site-packages\poetry\repositories\pypi_repository.py:158 in find_links_for_package 156│ 157│ def find_links_for_package(self, package: Package) -> list[Link]: → 158│ json_data = self._get(f"pypi/{package.name}/{package.version}/json") 159│ if json_data is None: 160│ return []
13 C:\Program Files\Python310\lib\site-packages\poetry\repositories\pypi_repository.py:246 in _get 244│ ) -> dict[str, Any] | None: 245│ try: → 246│ json_response = self.session.get( 247│ self._base_url + endpoint, 248│ raise_for_status=False,
12 C:\Program Files\Python310\lib\site-packages\poetry\utils\authenticator.py:247 in get 245│ 246│ def get(self, url: str, kwargs: Any) -> requests.Response: → 247│ return self.request("get", url, kwargs) 248│ 249│ def post(self, url: str, **kwargs: Any) -> requests.Response:
11 C:\Program Files\Python310\lib\site-packages\poetry\utils\authenticator.py:188 in request 186│ headers = kwargs.get("headers") 187│ request = requests.Request(method, url, headers=headers) → 188│ credential = self.get_credentials_for_url(url) 189│ 190│ if credential.username is not None or credential.password is not None:
10 C:\Program Files\Python310\lib\site-packages\poetry\utils\authenticator.py:311 in get_credentials_for_url 309│ # no credentials were provided in the url, try finding the 310│ # best repository configuration → 311│ self._credentials[url] = self._get_credentials_for_url(url) 312│ else: 313│ # Split from the right because that's how urllib.parse.urlsplit()
9 C:\Program Files\Python310\lib\site-packages\poetry\utils\authenticator.py:272 in _get_credentials_for_url 270│ 271│ credential = ( → 272│ self._get_credentials_for_repository(repository=repository) 273│ if repository is not None 274│ else HTTPAuthCredential()
8 C:\Program Files\Python310\lib\site-packages\poetry\utils\authenticator.py:260 in _get_credentials_for_repository 258│ 259│ if key not in self._credentials: → 260│ self._credentials[key] = repository.get_http_credentials( 261│ password_manager=self._password_manager, username=username 262│ )
7 C:\Program Files\Python310\lib\site-packages\poetry\utils\authenticator.py:90 in get_http_credentials 88│ if credential.password is None: 89│ # fallback to url and netloc based keyring entries → 90│ credential = password_manager.keyring.get_credential( 91│ self.url, self.netloc, username=credential.username 92│ )
6 C:\Program Files\Python310\lib\site-packages\poetry\utils\password_manager.py:51 in get_credential 49│ 50│ for name in names: → 51│ credential = keyring.get_credential(name, username) 52│ if credential: 53│ return HTTPAuthCredential(
5 C:\Program Files\Python310\lib\site-packages\keyring\core.py:72 in get_credential 70│ ) -> typing.Optional[credentials.Credential]: 71│ """Get a Credential for the specified service.""" → 72│ return get_keyring().get_credential(service_name, username) 73│ 74│
4 C:\Program Files\Python310\lib\site-packages\keyring\backends\Windows.py:167 in get_credential 165│ # get any first password under the service name 166│ if not res: → 167│ res = self._get_password(service) 168│ if not res: 169│ return None
3 C:\Program Files\Python310\lib\site-packages\keyring\backends\Windows.py:108 in _get_password 106│ def _get_password(self, target): 107│ try: → 108│ res = win32cred.CredRead( 109│ Type=win32cred.CRED_TYPE_GENERIC, TargetName=target 110│ )
2 C:\Program Files\Python310\lib\site-packages\win32ctypes\pywin32\win32cred.py:63 in CredRead 61│ 62│ flag = 0 → 63│ with _pywin32error(): 64│ if _backend == 'cffi': 65│ ppcreds = _authentication.PPCREDENTIAL()
1 C:\Program Files\Python310\lib\contextlib.py:153 in exit 151│ value = typ() 152│ try: → 153│ self.gen.throw(typ, value, traceback) 154│ except StopIteration as exc: 155│ # Suppress StopIteration unless it's the same exception that
error
(1312, 'CredRead', 'A specified logon session does not exist. It may already have been terminated.')
at C:\Program Files\Python310\lib\site-packages\win32ctypes\pywin32\pywintypes.py:37 in pywin32error 33│ def pywin32error(): 34│ try: 35│ yield 36│ except WindowsError as exception: → 37│ raise error(exception.winerror, exception.function, exception.strerror) 38│
Please try and refrain from "me too" style comments given the number of participants in this issue. A :+1: is a simple way to show support/interest, and doesn't generate unnecessary notifications.
@neersighted is this expected behavior or is there any downside to making keyring optional alltogether? I am asking because I am also running poetry in (1) CI pipelines and also on (2) headless servers. Both do not have a keyring, thus Poetry 1.2 basically is unusable there without the PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
workaround.
CI pipelines usually do not need a keyring.
For headless servers we SSH agent forwarding, which is super neat for Git
and any ssh
based stuff on the server, thus also no local keyring needed.
I would guess that there are lots of CI pipelines, headless servers, nodes in datacenters, ... where simply no keyring will be present and it is often also not an option to set one up.
I'm running into this issue now, which makes Poetry unusable out-of-the-box.
Setting PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
seems to work.
Please refrain from "me too" comments in this issue given the number of participants.
@Daniel451, having Keyring in the loop by default is a requirement for many users (e.g. it's the only non-painful way to auth against Azure and GCP). Keyring does more than access the OS keyring.
Instead, we should really just improve the error handling so that a keyring error is a warning but does not terminate Poetry. No one has started on this; PRs are welcome.
@neersighted i would very much doubt that more than 10% of poetry all users are using keyrings or ever will. So while great for these few, it break the workflow for 90% of all poetry users. Having it as a default even with a warning is a bad idea, as most users will never need keyrings.
In general it would be great if the keyring is only checked for publishing operations. If i don't publish I will never need the keyring. And even in that scenario i question if most people will use keyrings. Most publishing happens via CD an for CD platforms like github offer their own option to store secrets.
Why not make PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
the default (so setting the ENV var is unnecessary), and then set PYTHON_KEYRING_BACKEND
when a Keyring is actually needed?
The keyring is required to access private package indexes and Git repositories, and is used to store credentials in an encrypted fashion when possible. Yes, this does not cover CI use-cases, but the intention was for this to be transparent to the end user. Keyring will not get in your way in CI; Poetry will transparently fall back to its own credential management.
Fundamentally, the issue here is that Keyring can jam on irregular/unexpected configurations (e.g. dbus present but no Keyring provider, Keyring provider refuses to unlock/report status, etc) and bubbles up exceptions from the underlying Python-platform API code to Poetry. Poetry needs to gracefully degrade here; modifying the existing code to fall back as if keyring was not present if this is the case should be the goal.
The keyring is required to access private package indexes and Git repositories, and is used to store credentials in an encrypted fashion when possible.
I wonder how many people are using private package indexes and git repos that require authentication for dependencies? Is it the majority of users, seems unlikely to me, but I could be wrong. :)
In any case, until this is fixed, could a poetry config be added that stopped poetry from trying to use the keyring? The posted workaround of using an environment variable or uninstalling keyring affects all of python not just poetry.
Thanks, Chris..
I was wrapping my head around this issue for over an hour. I'm using WSL2 and was testing on Ubuntu. I unregistered the VM and used an older clean version, and the problem was fixed.
I wish i had logged the values from keyring --list-backends
.
The current one is as follow:
keyring.backends.chainer.ChainerBackend (priority: -10)
keyring.backends.fail.Keyring (priority: 0)
But i'm 100% sure there was a third one when i was facing this issue. I can't seem to remember it's name... Can someone please run this command and post the output here too?
Using keyring.backends.null.Keyring
didn't fix it for me.
Anyway, it seems like i'm now using fail as a backend, so maybe this can be helpful to someone:
export PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring
And to set it at startup (on bash)
echo export PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring >> $HOME/.profile
In my case this is cased by https://github.com/jaraco/keyring/issues/496 - the chainer
backend is getting priority, it checks the KDE one, and it's unable to check the KDE one without causing a prompt for me to set up a KDE Wallet (I'm on Gnome...)
@dimbleby pointed this out to me, for which I am much grateful.
Is it possible to make additional features delivery through plug-ins system, since such changes have a strong effect on CI/CD systems and breaking a painless transition to new versions and create such workaround search discussions?
Just found a way to disable keyring according to this post, which finally fixes my issue 😭 : https://connormcf.com/blog/poetry-failed-to-unlock/
Happened to me today for the first time. I used Poetry until last month without any issues, but today I saw same error.
export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
seems to fix the issue.
Where should I add this export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
?
@emilh18 Hi, in your Unix/Linux shell (bash
in most cases)
There are several ways to do that:
1) First, export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
will work for following poetry commands until you close (exit) your shell session
2) Add environment variable for each! poetry command, for example PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring poetry install
3) If you want to preserve (store) this environment variable between shell sessions or system reboot you can add it in .bashrc
and .profile
example for bash shell:
echo 'export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring' >> ~/.bashrc
echo 'export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring' >> ~/.profile
exec "$SHELL"
for case number 3) you can now run any poetry command as usual, even after system restart
@emilh18 Hi, in your Unix/Linux shell (
bash
in most cases)There are several ways to do that:
1. First, `export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring` will work for following poetry commands until you close (exit) your shell session 2. Add environment variable for **each**! poetry command, for example `PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring poetry install` 3. If you want to preserve (store) this environment variable between shell sessions or system reboot you can add it in `.bashrc` and `.profile` example for bash shell:
echo 'export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring' >> ~/.bashrc echo 'export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring' >> ~/.profile exec "$SHELL"
for case number 3) you can now run any poetry command as usual, even after system restart
If this doesn't work, check your ~/.bashrc
or ~/.profile
. It's most likely that it has been appended to the last commented line.
Ah, wtf, I'm searching Google then found my own comment..
I have many pipenv based projects, today I tried Poetry for the first time and I hit this issue.
I am developing in vscode, on a remote host (often also in a devcontainer on a remote host)
I use ssh-agent forwarding and ssh based git access to local packages in gitlab when working with pipenv. That matches how my gitlab ci file is setup (and also works well with Dockerfile), so I can use one access method in multiple environments for the same project.
I suppose poetry might want to save gitlab access tokens (which would also work in gitlab-ci).
I think it might be a little friendlier if poetry didn't demand keyring access unless it knew it was actually needed. Perhaps it can set a flag in pyproject.toml (or parse it) to see if access to a keyring is actually required.
But since I've been using poetry for all of 15 minutes, I probably do not have the full picture.
I will be disappointed if I have to put env PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
in my gitlab-ci file.
As other commenters have noted, the default behavior is quite broken. I've worked around the issue by preparing a custom distribution package of Poetry that patches out the issue, as follows:
Needless to say, I really hope this is fixed. Of course Poetry should not attempt to load a keyring until an operation is requested by the user which actually needs credentials.
Hopefully this is helpful for maintainers. I just built a fresh server with Pop!_OS 22.04 LTS
. I then did:
That gave me Failed to unlock the collection!
which was not a helpful error message. Which collection? Searching brought me here.
Applying the export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
command made things work for me. But were I not a dedicated Poetry user, I would have decided it wasn't ready for prime time and uninstalled it.
Ok I solved it for my poetry inside windows machine without any GUI.
python -m pip install keyring
python -m keyring --disable
I tried to use PYTHON_KEYRING_BACKEND
but it does not work for me because I had no installed keyring. Poetry need to avoid to use keyring. This is a huge problem for Windows and Linux especially when you want to use it inside Docker/Qemu
Enjoy!
I use the keyring for an different application. So i solved the issue by commenting out at
~/.local/share/pypoetry/venv/lib/python3.9/site-packages/poetry/utils/authenticator.py:219
def request(
self, method: str, url: str, raise_for_status: bool = True, **kwargs: Any
) -> requests.Response:
headers = kwargs.get("headers")
request = requests.Request(method, url, headers=headers)
# credential = self.get_credentials_for_url(url)
# if credential.username is not None or credential.password is not None:
# request = requests.auth.HTTPBasicAuth(
# credential.username or "", credential.password or ""
# )(request)
...
It would be nice to have some config flag to disable this functionality. I imagine such flag would belong here
[[tool.poetry.source]]
name = "private"
url = "https://pypi.private_ip_protected_repo.com"
nokeyring = true
if you are using ssh to access your work environment add this function to your .bashrc file.
from https://unix.stackexchange.com/questions/602313/unlock-gnome-keyring-daemon-from-command-line
# Linux unlock gnome keyring function unlock-keyring () { read -rsp "Password: " pass export $(echo -n "$pass" | gnome-keyring-daemon --replace --unlock) unset pass }
I gather that keyring integration was added as a convenience feature so that you can publish packages using keys stored in your keyring. This ticket describes that feature:
https://github.com/python-poetry/poetry/issues/210
But it appears that poetry tries to access the keyring even for install operations. In one of my first times using poetry - I, as a security paranoid person, decided to abort installation of a py package I wanted because the installation process seemed to be wanting to access my keyring.
I think people should be careful about granting programs access to things they should not need to access. This behavior is an example of a problem that makes that hard to achieve.
For me, I worked around the problem by pip uninstalling the 'keyring' package from that virt env.
In the future, I think it would be beneficial to poetry's adoption and to its users, if users are not prompted for keyring unless keys should actually be needed (for a 'publish' operation).
Thanks! I'm happy to be trying out poetry.