Skip to content

Commit 5bc7149

Browse files
authored
Merge pull request #695 from ffissore/anon-fix
Not accessing `credentials.username` if `credentials` is an instance of `AnonymousCredential`
2 parents 0041050 + e9f7851 commit 5bc7149

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

keyring/cli.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,11 @@ def do_get(self):
132132
getattr(self, f'_emit_{self.output_format}')(credential)
133133

134134
def _emit_json(self, credential: credentials.Credential):
135-
print(
136-
json.dumps(dict(username=credential.username, password=credential.password))
137-
)
135+
print(json.dumps(credential._vars()))
138136

139137
def _emit_plain(self, credential: credentials.Credential):
140-
if credential.username:
141-
print(credential.username)
142-
print(credential.password)
138+
for val in credential._vars().values():
139+
print(val)
143140

144141
def _get_creds(self) -> credentials.Credential | None:
145142
return get_credential(self.service, self.username)

keyring/credentials.py

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ def username(self) -> str: ...
1313
@abc.abstractproperty
1414
def password(self) -> str: ...
1515

16+
def _vars(self) -> dict[str, str]:
17+
return dict(username=self.username, password=self.password)
18+
1619

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

44+
def _vars(self) -> dict[str, str]:
45+
return dict(password=self.password)
46+
4147

4248
class EnvironCredential(Credential):
4349
"""

newsfragments/694.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed ValueError for AnonymousCredentials in CLI.

tests/test_cli.py

+31
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pytest
77

88
from keyring import cli
9+
from keyring import credentials
910

1011
flatten = itertools.chain.from_iterable
1112

@@ -36,6 +37,12 @@ def mocked_set():
3637
yield set_password
3738

3839

40+
@pytest.fixture
41+
def mocked_get_credential():
42+
with mock.patch('keyring.cli.get_credential') as get_credential:
43+
yield get_credential
44+
45+
3946
def test_set_interactive(monkeypatch, mocked_set):
4047
tool = cli.CommandLineTool()
4148
tool.service = 'svc'
@@ -64,3 +71,27 @@ def test_set_pipe_newline(monkeypatch, mocked_set):
6471
monkeypatch.setattr(sys.stdin, 'read', lambda: 'foo123\n')
6572
tool.do_set()
6673
mocked_set.assert_called_once_with('svc', 'usr', 'foo123')
74+
75+
76+
@pytest.mark.parametrize('format', ['json', 'plain'])
77+
def test_get_anonymous(monkeypatch, mocked_get_credential, format, capsys):
78+
mocked_get_credential.return_value = credentials.AnonymousCredential('s3cret')
79+
tool = cli.CommandLineTool()
80+
tool.service = 'svc'
81+
tool.username = None
82+
tool.get_mode = 'creds'
83+
tool.output_format = format
84+
tool.do_get()
85+
assert 's3cret' in capsys.readouterr().out
86+
87+
88+
@pytest.mark.parametrize('format', ['json', 'plain'])
89+
def test_get(monkeypatch, mocked_get_credential, format, capsys):
90+
mocked_get_credential.return_value = credentials.SimpleCredential('alice', 's3cret')
91+
tool = cli.CommandLineTool()
92+
tool.service = 'svc'
93+
tool.username = 'alice'
94+
tool.get_mode = 'creds'
95+
tool.output_format = format
96+
tool.do_get()
97+
assert 's3cret' in capsys.readouterr().out

0 commit comments

Comments
 (0)