From a72021fe32d6b4aec98ccc42ec7b681780904aa5 Mon Sep 17 00:00:00 2001 From: Yesha Date: Sat, 25 Jul 2020 15:59:30 -0700 Subject: [PATCH 1/3] Update tests for non-interactive and client_cert --- AUTHORS | 1 + tests/test_settings.py | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/AUTHORS b/AUTHORS index 3fa60e85..4d5da32b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -28,3 +28,4 @@ Brian Rutledge Peter Stensmyr (http://www.peterstensmyr.com) Felipe Mulinari Rocha Campos Devesh Kumar Singh +Yesha Maggi diff --git a/tests/test_settings.py b/tests/test_settings.py index 972b8c76..5b5c2385 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -74,14 +74,6 @@ def test_identity_requires_sign(): settings.Settings(sign=False, identity="fakeid") -def test_password_not_required_if_client_cert(entered_password): - """Don't set password when only client_cert is provided.""" - test_client_cert = "/random/path" - settings_obj = settings.Settings(username="fakeuser", client_cert=test_client_cert) - assert not settings_obj.password - assert settings_obj.client_cert == test_client_cert - - @pytest.mark.parametrize("client_cert", [None, ""]) def test_password_is_required_if_no_client_cert(client_cert, entered_password): """Set password when client_cert is not provided.""" @@ -89,16 +81,32 @@ def test_password_is_required_if_no_client_cert(client_cert, entered_password): assert settings_obj.password == "entered pw" -def test_client_cert_is_set_and_password_not_if_both_given(entered_password): +def test_client_cert_and_password_both_set_if_given(): """Set password and client_cert when both are provided.""" client_cert = "/random/path" settings_obj = settings.Settings( username="fakeuser", password="anything", client_cert=client_cert ) - assert not settings_obj.password + assert settings_obj.password == "anything" assert settings_obj.client_cert == client_cert +def test_password_required_if_no_client_cert_and_non_interactive(): + """Raise exception if no password or client_cert when non interactive.""" + settings_obj = settings.Settings(username="fakeuser", non_interactive=True) + with pytest.raises(exceptions.NonInteractive): + settings_obj.password + + +def test_no_password_prompt_if_client_cert_and_non_interactive(entered_password): + """Don't prompt for password when client_cert is provided and non interactive.""" + client_cert = "/random/path" + settings_obj = settings.Settings( + username="fakeuser", client_cert=client_cert, non_interactive=True + ) + assert not settings_obj.password + + class TestArgumentParsing: @staticmethod def parse_args(args): From 08a82a7650e6efaa5b30637908dd4d2382ad02b7 Mon Sep 17 00:00:00 2001 From: Yesha Date: Sat, 25 Jul 2020 16:40:43 -0700 Subject: [PATCH 2/3] Password optional if client_cert is set --- twine/settings.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/twine/settings.py b/twine/settings.py index 73d4608c..d7128687 100644 --- a/twine/settings.py +++ b/twine/settings.py @@ -145,7 +145,10 @@ def username(self) -> Optional[str]: @property def password(self) -> Optional[str]: if self.client_cert: - return None + try: + return cast(Optional[str], self.auth.password) + except exceptions.NonInteractive: + return None # Workaround for https://github.com/python/mypy/issues/5858 return cast(Optional[str], self.auth.password) From e15122e027bc931c5a5fa6c5307b98e3f6c434ae Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 9 Aug 2020 21:03:11 -0400 Subject: [PATCH 3/3] Extract _allow_noninteractive method to suppress NonInteractive error. --- twine/settings.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/twine/settings.py b/twine/settings.py index d7128687..2dac15ef 100644 --- a/twine/settings.py +++ b/twine/settings.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. import argparse +import contextlib import logging import sys from typing import Any +from typing import ContextManager from typing import Optional from typing import cast @@ -144,14 +146,14 @@ def username(self) -> Optional[str]: @property def password(self) -> Optional[str]: - if self.client_cert: - try: - return cast(Optional[str], self.auth.password) - except exceptions.NonInteractive: - return None - - # Workaround for https://github.com/python/mypy/issues/5858 - return cast(Optional[str], self.auth.password) + with self._allow_noninteractive(): + # Workaround for https://github.com/python/mypy/issues/5858 + return cast(Optional[str], self.auth.password) + + def _allow_noninteractive(self) -> ContextManager[None]: + """Bypass NonInteractive error when client cert is present.""" + suppressed = (exceptions.NonInteractive,) if self.client_cert else () + return contextlib.suppress(*suppressed) @property def verbose(self) -> bool: