diff --git a/news/7998.bugfix b/news/7998.bugfix new file mode 100644 index 00000000000..aec751f86a0 --- /dev/null +++ b/news/7998.bugfix @@ -0,0 +1 @@ +Prompt the user for password if the keyring backend doesn't return one diff --git a/src/pip/_internal/network/auth.py b/src/pip/_internal/network/auth.py index 94da3d46aaa..ab8ac07012e 100644 --- a/src/pip/_internal/network/auth.py +++ b/src/pip/_internal/network/auth.py @@ -219,7 +219,7 @@ def _prompt_for_password(self, netloc): if not username: return None, None auth = get_keyring_auth(netloc, username) - if auth: + if auth and auth[0] is not None and auth[1] is not None: return auth[0], auth[1], False password = ask_password("Password: ") return username, password, True diff --git a/tests/unit/test_network_auth.py b/tests/unit/test_network_auth.py index 1fadd1db348..08320cfa143 100644 --- a/tests/unit/test_network_auth.py +++ b/tests/unit/test_network_auth.py @@ -123,6 +123,26 @@ def ask_input(prompt): assert actual == ("user", "user!netloc", False) +def test_keyring_get_password_after_prompt_when_none(monkeypatch): + keyring = KeyringModuleV1() + monkeypatch.setattr('pip._internal.network.auth.keyring', keyring) + auth = MultiDomainBasicAuth() + + def ask_input(prompt): + assert prompt == "User for unknown.com: " + return "user" + + def ask_password(prompt): + assert prompt == "Password: " + return "fake_password" + + monkeypatch.setattr('pip._internal.network.auth.ask_input', ask_input) + monkeypatch.setattr( + 'pip._internal.network.auth.ask_password', ask_password) + actual = auth._prompt_for_password("unknown.com") + assert actual == ("user", "fake_password", True) + + def test_keyring_get_password_username_in_index(monkeypatch): keyring = KeyringModuleV1() monkeypatch.setattr('pip._internal.network.auth.keyring', keyring)