From 030aaaad4a6439ffe7539905bd999c720f7aa5df Mon Sep 17 00:00:00 2001 From: Popkornium18 Date: Fri, 26 Jan 2024 17:18:08 +0100 Subject: [PATCH] add config option keyring.enabled to allow disabling the keyring --- docs/configuration.md | 10 ++++++++++ docs/repositories.md | 6 ++++++ src/poetry/config/config.py | 3 +++ src/poetry/console/commands/config.py | 1 + src/poetry/utils/password_manager.py | 2 +- tests/console/commands/test_config.py | 6 ++++++ tests/utils/test_password_manager.py | 11 +++++++++++ 7 files changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 67a0301c3cd..bef91432e0f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -506,3 +506,13 @@ repository. Set client certificate for repository ``. See [Repositories - Configuring credentials - Custom certificate authority]({{< relref "repositories#custom-certificate-authority-and-mutual-tls-authentication" >}}) for more information. + +### `keyring.enabled`: + +**Type**: `boolean` + +**Default**: `true` + +Enable the system keyring for storing credentials. +See [Repositories - Configuring credentials]({{< relref "repositories#configuring-credentials" >}}) +for more information. diff --git a/docs/repositories.md b/docs/repositories.md index a06d45f9f46..b7ecd35b4d5 100644 --- a/docs/repositories.md +++ b/docs/repositories.md @@ -480,6 +480,12 @@ If a system keyring is available and supported, the password is stored to and re Keyring support is enabled using the [keyring library](https://pypi.org/project/keyring/). For more information on supported backends refer to the [library documentation](https://keyring.readthedocs.io/en/latest/?badge=latest). +If you do not want to use the keyring you can tell Poetry to disable it and store the credentials in plaintext config files: + +```bash +poetry config keyring.enabled false +``` + {{% note %}} Poetry will fallback to Pip style use of keyring so that backends like diff --git a/src/poetry/config/config.py b/src/poetry/config/config.py index 5bafb90218b..816e828ab04 100644 --- a/src/poetry/config/config.py +++ b/src/poetry/config/config.py @@ -137,6 +137,9 @@ class Config: "warnings": { "export": True, }, + "keyring": { + "enabled": True, + }, } def __init__( diff --git a/src/poetry/console/commands/config.py b/src/poetry/console/commands/config.py index 13e8b2262a0..3d0162e12c0 100644 --- a/src/poetry/console/commands/config.py +++ b/src/poetry/console/commands/config.py @@ -79,6 +79,7 @@ def unique_config_values(self) -> dict[str, tuple[Any, Any]]: ), "solver.lazy-wheel": (boolean_validator, boolean_normalizer), "warnings.export": (boolean_validator, boolean_normalizer), + "keyring.enabled": (boolean_validator, boolean_normalizer), } return unique_config_values diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 1b7aa2e8d32..a0ac8926bd3 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -145,7 +145,7 @@ def __init__(self, config: Config) -> None: @functools.cached_property def use_keyring(self) -> bool: - return PoetryKeyring.is_available() + return self._config.get("keyring.enabled") and PoetryKeyring.is_available() @functools.cached_property def keyring(self) -> PoetryKeyring: diff --git a/tests/console/commands/test_config.py b/tests/console/commands/test_config.py index 6c15e6a35fb..80fc1571197 100644 --- a/tests/console/commands/test_config.py +++ b/tests/console/commands/test_config.py @@ -59,6 +59,7 @@ def test_list_displays_default_value_if_not_set( installer.modern-installation = true installer.no-binary = null installer.parallel = true +keyring.enabled = true solver.lazy-wheel = true virtualenvs.create = true virtualenvs.in-project = null @@ -90,6 +91,7 @@ def test_list_displays_set_get_setting( installer.modern-installation = true installer.no-binary = null installer.parallel = true +keyring.enabled = true solver.lazy-wheel = true virtualenvs.create = false virtualenvs.in-project = null @@ -142,6 +144,7 @@ def test_unset_setting( installer.modern-installation = true installer.no-binary = null installer.parallel = true +keyring.enabled = true solver.lazy-wheel = true virtualenvs.create = true virtualenvs.in-project = null @@ -172,6 +175,7 @@ def test_unset_repo_setting( installer.modern-installation = true installer.no-binary = null installer.parallel = true +keyring.enabled = true solver.lazy-wheel = true virtualenvs.create = true virtualenvs.in-project = null @@ -301,6 +305,7 @@ def test_list_displays_set_get_local_setting( installer.modern-installation = true installer.no-binary = null installer.parallel = true +keyring.enabled = true solver.lazy-wheel = true virtualenvs.create = false virtualenvs.in-project = null @@ -339,6 +344,7 @@ def test_list_must_not_display_sources_from_pyproject_toml( installer.modern-installation = true installer.no-binary = null installer.parallel = true +keyring.enabled = true repositories.foo.url = "https://foo.bar/simple/" solver.lazy-wheel = true virtualenvs.create = true diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index bf942da233e..b0295c62752 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -330,3 +330,14 @@ def test_get_pypi_token_with_env_var_not_available( result_token = manager.get_pypi_token(repo_name) assert result_token is None + + +def test_disabled_keyring_is_unavailable( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +) -> None: + manager = PasswordManager(config) + assert manager.use_keyring + + config.config["keyring"]["enabled"] = False + manager = PasswordManager(config) + assert not manager.use_keyring