Skip to content

Commit

Permalink
Merge pull request #695 from ffissore/anon-fix
Browse files Browse the repository at this point in the history
Not accessing `credentials.username` if `credentials` is an instance of `AnonymousCredential`
  • Loading branch information
jaraco authored Sep 20, 2024
2 parents 0041050 + e9f7851 commit 5bc7149
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 6 deletions.
9 changes: 3 additions & 6 deletions keyring/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,11 @@ def do_get(self):
getattr(self, f'_emit_{self.output_format}')(credential)

def _emit_json(self, credential: credentials.Credential):
print(
json.dumps(dict(username=credential.username, password=credential.password))
)
print(json.dumps(credential._vars()))

def _emit_plain(self, credential: credentials.Credential):
if credential.username:
print(credential.username)
print(credential.password)
for val in credential._vars().values():
print(val)

def _get_creds(self) -> credentials.Credential | None:
return get_credential(self.service, self.username)
Expand Down
6 changes: 6 additions & 0 deletions keyring/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ def username(self) -> str: ...
@abc.abstractproperty
def password(self) -> str: ...

def _vars(self) -> dict[str, str]:
return dict(username=self.username, password=self.password)


class SimpleCredential(Credential):
"""Simple credentials implementation"""
Expand All @@ -38,6 +41,9 @@ def __init__(self, password: str):
def username(self) -> str:
raise ValueError("Anonymous credential has no username")

def _vars(self) -> dict[str, str]:
return dict(password=self.password)


class EnvironCredential(Credential):
"""
Expand Down
1 change: 1 addition & 0 deletions newsfragments/694.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed ValueError for AnonymousCredentials in CLI.
31 changes: 31 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest

from keyring import cli
from keyring import credentials

flatten = itertools.chain.from_iterable

Expand Down Expand Up @@ -36,6 +37,12 @@ def mocked_set():
yield set_password


@pytest.fixture
def mocked_get_credential():
with mock.patch('keyring.cli.get_credential') as get_credential:
yield get_credential


def test_set_interactive(monkeypatch, mocked_set):
tool = cli.CommandLineTool()
tool.service = 'svc'
Expand Down Expand Up @@ -64,3 +71,27 @@ def test_set_pipe_newline(monkeypatch, mocked_set):
monkeypatch.setattr(sys.stdin, 'read', lambda: 'foo123\n')
tool.do_set()
mocked_set.assert_called_once_with('svc', 'usr', 'foo123')


@pytest.mark.parametrize('format', ['json', 'plain'])
def test_get_anonymous(monkeypatch, mocked_get_credential, format, capsys):
mocked_get_credential.return_value = credentials.AnonymousCredential('s3cret')
tool = cli.CommandLineTool()
tool.service = 'svc'
tool.username = None
tool.get_mode = 'creds'
tool.output_format = format
tool.do_get()
assert 's3cret' in capsys.readouterr().out


@pytest.mark.parametrize('format', ['json', 'plain'])
def test_get(monkeypatch, mocked_get_credential, format, capsys):
mocked_get_credential.return_value = credentials.SimpleCredential('alice', 's3cret')
tool = cli.CommandLineTool()
tool.service = 'svc'
tool.username = 'alice'
tool.get_mode = 'creds'
tool.output_format = format
tool.do_get()
assert 's3cret' in capsys.readouterr().out

0 comments on commit 5bc7149

Please sign in to comment.