Skip to content

Commit d6db7e5

Browse files
committed
refactor: Rename CredentialProvider to ArtifactsHelperCredentialProvider
Also renames the test files to correspond to the exercised source file.
1 parent e4110fc commit d6db7e5

5 files changed

Lines changed: 61 additions & 54 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
from .artifacts_helper_wrapper import CredentialProvider
1+
from .artifacts_helper_credential_provider import ArtifactsHelperCredentialProvider
22
from .keyring_backend import CodespacesArtifactsHelperKeyringBackend

src/artifacts-helper/codespaces_artifacts_helper_keyring/src/codespaces_artifacts_helper_keyring/artifacts_helper_wrapper.py renamed to src/artifacts-helper/codespaces_artifacts_helper_keyring/src/codespaces_artifacts_helper_keyring/artifacts_helper_credential_provider.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ class Credentials:
2222
password: str
2323

2424

25-
class CredentialProviderError(RuntimeError):
25+
class ArtifactsHelperCredentialProviderError(RuntimeError):
2626
pass
2727

2828

29-
class CredentialProvider:
29+
class ArtifactsHelperCredentialProvider:
3030
DEFAULT_AUTH_HELPER_PATH = "~/ado-auth-helper"
3131

3232
def __init__(
@@ -39,20 +39,18 @@ def __init__(
3939

4040
@staticmethod
4141
def resolve_auth_helper_path(
42-
auth_helper_path: Union[os.PathLike, str], ) -> Optional[str]:
43-
return shutil.which(str(Path(auth_helper_path).expanduser()),
44-
mode=os.X_OK)
42+
auth_helper_path: Union[os.PathLike, str],
43+
) -> Optional[str]:
44+
return shutil.which(str(Path(auth_helper_path).expanduser()), mode=os.X_OK)
4545

4646
@classmethod
47-
def auth_helper_installed(
48-
cls, auth_helper_path: Union[os.PathLike, str]) -> bool:
47+
def auth_helper_installed(cls, auth_helper_path: Union[os.PathLike, str]) -> bool:
4948
return cls.resolve_auth_helper_path(auth_helper_path) is not None
5049

5150
def get_credentials(self, url) -> Optional[Credentials]:
5251
# Public feed short circuit: return nothing if not getting credentials for the upload endpoint
5352
# (which always requires auth) and the endpoint is public (can authenticate without credentials).
54-
if not self._is_upload_endpoint(url) and self._can_authenticate(
55-
url, None):
53+
if not self._is_upload_endpoint(url) and self._can_authenticate(url, None):
5654
return None
5755

5856
jwt_str = self._get_jwt_from_helper()
@@ -68,13 +66,13 @@ def _is_upload_endpoint(url) -> bool:
6866

6967
def _can_authenticate(self, url, auth) -> bool:
7068
response = requests.get(url, auth=auth, timeout=self.timeout)
71-
return response.status_code < 500 and response.status_code not in (401,
72-
403)
69+
return response.status_code < 500 and response.status_code not in (401, 403)
7370

7471
def _get_jwt_from_helper(self) -> str:
7572
if self.auth_tool_path is None:
76-
raise CredentialProviderError(
77-
"Failed to get credentials: No authentication tool found")
73+
raise ArtifactsHelperCredentialProviderError(
74+
"Failed to get credentials: No authentication tool found"
75+
)
7876

7977
try:
8078
p = subprocess.run(
@@ -88,27 +86,29 @@ def _get_jwt_from_helper(self) -> str:
8886
if stdout:
8987
return stdout.strip()
9088
else:
91-
raise CredentialProviderError(
89+
raise ArtifactsHelperCredentialProviderError(
9290
f"Failed to get credentials: No output from subprocess {self.auth_tool_path}"
9391
)
9492

9593
except subprocess.CalledProcessError as e:
96-
raise CredentialProviderError(
94+
raise ArtifactsHelperCredentialProviderError(
9795
f"Failed to get credentials: Process {self.auth_tool_path} exited with code {e.returncode}. Error: {e.stderr}"
9896
) from e
9997
except subprocess.TimeoutExpired as e:
100-
raise CredentialProviderError(
98+
raise ArtifactsHelperCredentialProviderError(
10199
f"Failed to get credentials: Process {self.auth_tool_path} timed out after {self.timeout} seconds"
102100
) from e
103101

104102
def _get_credentials_from_jwt(self, jwt_str: str) -> Credentials:
105103
try:
106-
decoded = jwt.decode(jwt_str,
107-
verify=False,
108-
options={"verify_signature": False})
104+
decoded = jwt.decode(
105+
jwt_str, verify=False, options={"verify_signature": False}
106+
)
109107
return Credentials(
110108
username=decoded.get("unique_name", decoded.get("upn", None)),
111109
password=jwt_str,
112110
)
113111
except jwt.PyJWTError as e:
114-
raise CredentialProviderError(f"Failed to decode JWT: {e}") from e
112+
raise ArtifactsHelperCredentialProviderError(
113+
f"Failed to decode JWT: {e}"
114+
) from e

src/artifacts-helper/codespaces_artifacts_helper_keyring/src/codespaces_artifacts_helper_keyring/keyring_backend.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from keyring.backend import KeyringBackend
77
from keyring.credentials import Credential, SimpleCredential
88

9-
from .artifacts_helper_wrapper import CredentialProvider
9+
from .artifacts_helper_credential_provider import ArtifactsHelperCredentialProvider
1010

1111

1212
class CodespacesArtifactsHelperKeyringBackend(KeyringBackend):
@@ -17,7 +17,9 @@ class CodespacesArtifactsHelperKeyringBackend(KeyringBackend):
1717
"pkgs.vsts.me",
1818
)
1919

20-
_PROVIDER: Type[CredentialProvider] = CredentialProvider
20+
_PROVIDER: Type[ArtifactsHelperCredentialProvider] = (
21+
ArtifactsHelperCredentialProvider
22+
)
2123
AUTH_HELPER_PATH = _PROVIDER.DEFAULT_AUTH_HELPER_PATH
2224

2325
@properties.classproperty

src/artifacts-helper/codespaces_artifacts_helper_keyring/tests/test_artifacts_helper_wrapper.py renamed to src/artifacts-helper/codespaces_artifacts_helper_keyring/tests/test_artifacts_helper_credential_provider.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import pytest
88
from codespaces_artifacts_helper_keyring import (
9-
CredentialProvider,
9+
ArtifactsHelperCredentialProvider,
1010
)
11-
from codespaces_artifacts_helper_keyring.artifacts_helper_wrapper import (
12-
CredentialProviderError,
11+
from codespaces_artifacts_helper_keyring.artifacts_helper_credential_provider import (
12+
ArtifactsHelperCredentialProviderError,
1313
)
1414

1515

@@ -38,61 +38,70 @@ def write_script(self, content: str, shebang: str = "#!/usr/bin/env python3"):
3838
set_path_executable(self.script_path)
3939

4040
def test_auth_helper_installed_invalid_path(self):
41-
assert not CredentialProvider.resolve_auth_helper_path(
41+
assert not ArtifactsHelperCredentialProvider.resolve_auth_helper_path(
4242
self.tmp_dir / "nonexistent"
4343
)
44-
assert not CredentialProvider.auth_helper_installed(
44+
assert not ArtifactsHelperCredentialProvider.auth_helper_installed(
4545
self.tmp_dir / "nonexistent"
4646
)
4747

4848
def test_auth_helper_installed_and_not_executable(self):
4949
self.write_script("pass")
5050
set_path_not_executable(self.script_path)
51-
assert not CredentialProvider.resolve_auth_helper_path(self.script_path)
52-
assert not CredentialProvider.auth_helper_installed(self.script_path)
51+
assert not ArtifactsHelperCredentialProvider.resolve_auth_helper_path(
52+
self.script_path
53+
)
54+
assert not ArtifactsHelperCredentialProvider.auth_helper_installed(
55+
self.script_path
56+
)
5357

5458
def test_auth_helper_installed_and_executable(self):
5559
self.write_script("pass")
56-
assert CredentialProvider.resolve_auth_helper_path(self.script_path) is not None
57-
assert CredentialProvider.auth_helper_installed(self.script_path)
60+
assert (
61+
ArtifactsHelperCredentialProvider.resolve_auth_helper_path(self.script_path)
62+
is not None
63+
)
64+
assert ArtifactsHelperCredentialProvider.auth_helper_installed(self.script_path)
5865

5966
def test_get_jwt_from_helper(self):
6067
raw_jwt_value = "raw_jwt_here._-azAZ09"
6168
self.write_script(f"print('{raw_jwt_value}')")
62-
provider = CredentialProvider(self.script_path)
69+
provider = ArtifactsHelperCredentialProvider(self.script_path)
6370
assert provider._get_jwt_from_helper() == raw_jwt_value.strip()
6471

6572
def test_get_jwt_from_helper_not_installed(self):
66-
provider = CredentialProvider()
73+
provider = ArtifactsHelperCredentialProvider()
6774
with pytest.raises(
68-
CredentialProviderError, match="No authentication tool found"
75+
ArtifactsHelperCredentialProviderError, match="No authentication tool found"
6976
):
7077
provider._get_jwt_from_helper()
7178

7279
def test_get_credentials_from_jwt(self):
73-
provider = CredentialProvider()
80+
provider = ArtifactsHelperCredentialProvider()
7481
creds = provider._get_credentials_from_jwt(self.TEST_JWT)
7582
assert creds.username == self.TEST_JWT_USERNAME
7683
assert creds.password == self.TEST_JWT
7784

7885
def test_get_credentials(self):
7986
self.write_script(f"print('{self.TEST_JWT}')")
80-
provider = CredentialProvider(self.script_path)
87+
provider = ArtifactsHelperCredentialProvider(self.script_path)
8188
creds = provider.get_credentials(self.SUPPORTED_HOST)
8289
assert creds.username == self.TEST_JWT_USERNAME
8390
assert creds.password == self.TEST_JWT
8491

8592
def test_get_credentials_invalid_jwt(self):
8693
self.write_script("print('invalid jwt')")
87-
provider = CredentialProvider(self.script_path)
88-
with pytest.raises(CredentialProviderError, match="Failed to decode JWT:"):
94+
provider = ArtifactsHelperCredentialProvider(self.script_path)
95+
with pytest.raises(
96+
ArtifactsHelperCredentialProviderError, match="Failed to decode JWT:"
97+
):
8998
provider.get_credentials(self.SUPPORTED_HOST)
9099

91100
def test_get_crendentials_helper_non_zero_exit(self):
92101
self.write_script("exit(1)")
93-
provider = CredentialProvider(self.script_path)
102+
provider = ArtifactsHelperCredentialProvider(self.script_path)
94103
with pytest.raises(
95-
CredentialProviderError,
104+
ArtifactsHelperCredentialProviderError,
96105
match=f"Process .*{self.script_name}.* exited with code 1",
97106
):
98107
provider.get_credentials(self.SUPPORTED_HOST)

src/artifacts-helper/codespaces_artifacts_helper_keyring/tests/test_backend.py renamed to src/artifacts-helper/codespaces_artifacts_helper_keyring/tests/test_keyring_backend.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import keyring.errors
1010
import pytest
1111
from codespaces_artifacts_helper_keyring import (
12+
ArtifactsHelperCredentialProvider,
1213
CodespacesArtifactsHelperKeyringBackend,
13-
CredentialProvider,
1414
)
1515
from keyring.credentials import SimpleCredential
1616

@@ -19,8 +19,7 @@
1919
SUPPORTED_HOST = "https://pkgs.dev.azure.com/"
2020

2121

22-
class FakeProvider(CredentialProvider):
23-
22+
class FakeProvider(ArtifactsHelperCredentialProvider):
2423
def get_credentials(self, service):
2524
return SimpleCredential("user" + service[-4:], "pass" + service[-4:])
2625

@@ -68,8 +67,7 @@ def passwords(monkeypatch):
6867
def mock_get_all_keyring():
6968
return [CodespacesArtifactsHelperKeyringBackend(), passwords_backend]
7069

71-
monkeypatch.setattr(keyring.backend, "get_all_keyring",
72-
mock_get_all_keyring)
70+
monkeypatch.setattr(keyring.backend, "get_all_keyring", mock_get_all_keyring)
7371

7472
chainer_backend = keyring.backends.chainer.ChainerBackend()
7573

@@ -81,8 +79,9 @@ def mock_get_all_keyring():
8179

8280
@pytest.fixture
8381
def fake_provider(monkeypatch):
84-
monkeypatch.setattr(CodespacesArtifactsHelperKeyringBackend, "_PROVIDER",
85-
FakeProvider)
82+
monkeypatch.setattr(
83+
CodespacesArtifactsHelperKeyringBackend, "_PROVIDER", FakeProvider
84+
)
8685

8786

8887
def test_get_credential_unsupported_host(only_backend):
@@ -102,8 +101,7 @@ def test_set_password_raises(only_backend):
102101

103102
def test_set_password_fallback(passwords, fake_provider):
104103
# Ensure we are getting good credentials
105-
assert keyring.get_credential(SUPPORTED_HOST + "1234",
106-
None).password == "pass1234"
104+
assert keyring.get_credential(SUPPORTED_HOST + "1234", None).password == "pass1234"
107105

108106
assert keyring.get_password("SYSTEM", "USERNAME") is None
109107
keyring.set_password("SYSTEM", "USERNAME", "PASSWORD")
@@ -113,8 +111,7 @@ def test_set_password_fallback(passwords, fake_provider):
113111
assert keyring.get_credential("SYSTEM", "USERNAME").password == "PASSWORD"
114112

115113
# Ensure we are getting good credentials
116-
assert keyring.get_credential(SUPPORTED_HOST + "1234",
117-
None).password == "pass1234"
114+
assert keyring.get_credential(SUPPORTED_HOST + "1234", None).password == "pass1234"
118115

119116

120117
def test_delete_password_raises(only_backend):
@@ -124,8 +121,7 @@ def test_delete_password_raises(only_backend):
124121

125122
def test_delete_password_fallback(passwords, fake_provider):
126123
# Ensure we are getting good credentials
127-
assert keyring.get_credential(SUPPORTED_HOST + "1234",
128-
None).password == "pass1234"
124+
assert keyring.get_credential(SUPPORTED_HOST + "1234", None).password == "pass1234"
129125

130126
passwords["SYSTEM", "USERNAME"] = "PASSWORD"
131127
keyring.delete_password("SYSTEM", "USERNAME")

0 commit comments

Comments
 (0)