Skip to content
Draft
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
24 changes: 12 additions & 12 deletions keyring/backends/SecretService.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def priority(cls) -> float:
secretstorage.__name__ # noqa: B018
if exc:
raise RuntimeError("SecretStorage required")
if secretstorage.__version_tuple__ < (3, 2):
raise RuntimeError("SecretStorage 3.2 or newer required")
if secretstorage.__version_tuple__ < (3, 5):
raise RuntimeError("SecretStorage 3.5 or newer required")
try:
with closing(secretstorage.dbus_init()) as connection:
if not secretstorage.check_service_availability(connection):
Expand All @@ -49,7 +49,7 @@ def priority(cls) -> float:
raise RuntimeError(f"Unable to initialize SecretService: {e}") from e
return 5

def get_preferred_collection(self):
def get_preferred_collection(self, timeout: float | None = None):
"""If self.preferred_collection contains a D-Bus path,
the collection at that address is returned. Otherwise,
the default collection is returned.
Expand All @@ -63,7 +63,7 @@ def get_preferred_collection(self):
except exceptions.SecretStorageException as e:
raise InitError(f"Failed to create the collection: {e}.") from e
if collection.is_locked():
collection.unlock()
collection.unlock(timeout=timeout)
if collection.is_locked(): # User dismissed the prompt
raise KeyringLocked("Failed to unlock the collection!")
return collection
Expand All @@ -74,33 +74,33 @@ def unlock(self, item):
if item.is_locked(): # User dismissed the prompt
raise KeyringLocked('Failed to unlock the item!')

def get_password(self, service, username):
def get_password(self, service, username, *, timeout: float | None = None):
"""Get password of the username for the service"""
collection = self.get_preferred_collection()
collection = self.get_preferred_collection(timeout=timeout)
with closing(collection.connection):
items = collection.search_items(self._query(service, username))
for item in items:
self.unlock(item)
return item.get_secret().decode('utf-8')

def set_password(self, service, username, password):
def set_password(self, service, username, password, *, timeout: float | None = None):
"""Set password for the username of the service"""
collection = self.get_preferred_collection()
collection = self.get_preferred_collection(timeout=timeout)
attributes = self._query(service, username, application=self.appid)
label = f"Password for '{username}' on '{service}'"
with closing(collection.connection):
collection.create_item(label, attributes, password, replace=True)

def delete_password(self, service, username):
def delete_password(self, service, username, *, timeout: float | None = None):
"""Delete the stored password (only the first one)"""
collection = self.get_preferred_collection()
collection = self.get_preferred_collection(timeout=timeout)
with closing(collection.connection):
items = collection.search_items(self._query(service, username))
for item in items:
return item.delete()
raise PasswordDeleteError("No such password!")

def get_credential(self, service, username):
def get_credential(self, service, username, *, timeout: float | None = None):
"""Gets the first username and password for a service.
Returns a Credential instance

Expand All @@ -110,7 +110,7 @@ def get_credential(self, service, username):
"""
scheme = self.schemes[self.scheme]
query = self._query(service, username)
collection = self.get_preferred_collection()
collection = self.get_preferred_collection(timeout=timeout)

with closing(collection.connection):
items = collection.search_items(query)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ requires-python = ">=3.9"
license = "MIT"
dependencies = [
'pywin32-ctypes>=0.2.0; sys_platform=="win32"',
'SecretStorage>=3.2; sys_platform=="linux"',
'SecretStorage>=3.5; sys_platform=="linux"',
'jeepney>=0.4.2; sys_platform=="linux"',
'importlib_metadata >= 4.11.4; python_version < "3.12"',
"jaraco.classes",
Expand Down
Loading