Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix client cert password bug #678

Merged
merged 3 commits into from
Aug 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ Brian Rutledge <[email protected]>
Peter Stensmyr <[email protected]> (http://www.peterstensmyr.com)
Felipe Mulinari Rocha Campos <[email protected]>
Devesh Kumar Singh <[email protected]>
Yesha Maggi <[email protected]>
28 changes: 18 additions & 10 deletions tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,31 +74,39 @@ 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."""
settings_obj = settings.Settings(username="fakeuser", client_cert=client_cert)
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):
Expand Down
15 changes: 10 additions & 5 deletions twine/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -144,11 +146,14 @@ def username(self) -> Optional[str]:

@property
def password(self) -> Optional[str]:
if self.client_cert:
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:
Expand Down