Skip to content

Commit

Permalink
Merge pull request #689 from dimbleby/type-annotations
Browse files Browse the repository at this point in the history
add a couple of type annotations
  • Loading branch information
jaraco authored Aug 22, 2024
2 parents ccdb048 + 8b8f666 commit f9bdb6e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 14 deletions.
4 changes: 1 addition & 3 deletions keyring/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,7 @@ def _get_creds(self) -> credentials.Credential | None:
def _get_password(self) -> credentials.Credential | None:
password = get_password(self.service, self.username) # type: ignore[attr-defined]
return (
credentials.SimpleCredential(None, password)
if password is not None
else None
credentials.AnonymousCredential(password) if password is not None else None
)

def do_set(self):
Expand Down
31 changes: 20 additions & 11 deletions keyring/credentials.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import abc
import os

Expand All @@ -6,30 +8,37 @@ class Credential(metaclass=abc.ABCMeta):
"""Abstract class to manage credentials"""

@abc.abstractproperty
def username(self):
return None
def username(self) -> str: ...

@abc.abstractproperty
def password(self):
return None
def password(self) -> str: ...


class SimpleCredential(Credential):
"""Simple credentials implementation"""

def __init__(self, username, password):
def __init__(self, username: str, password: str):
self._username = username
self._password = password

@property
def username(self):
def username(self) -> str:
return self._username

@property
def password(self):
def password(self) -> str:
return self._password


class AnonymousCredential(SimpleCredential):
def __init__(self, password: str):
self._password = password

@property
def username(self) -> str:
raise ValueError("Anonymous credential has no username")


class EnvironCredential(Credential):
"""
Source credentials from environment variables.
Expand All @@ -47,24 +56,24 @@ class EnvironCredential(Credential):
False
"""

def __init__(self, user_env_var, pwd_env_var):
def __init__(self, user_env_var: str, pwd_env_var: str):
self.user_env_var = user_env_var
self.pwd_env_var = pwd_env_var

def __eq__(self, other: object) -> bool:
return vars(self) == vars(other)

def _get_env(self, env_var):
def _get_env(self, env_var: str) -> str:
"""Helper to read an environment variable"""
value = os.environ.get(env_var)
if not value:
raise ValueError(f'Missing environment variable:{env_var}')
return value

@property
def username(self):
def username(self) -> str:
return self._get_env(self.user_env_var)

@property
def password(self):
def password(self) -> str:
return self._get_env(self.pwd_env_var)
1 change: 1 addition & 0 deletions newsfragments/689.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refined type spec and interfaces on credential objects. Introduced AnonymousCredential to model a secret without a username.

0 comments on commit f9bdb6e

Please sign in to comment.