Python bindings to FreeDesktop.org Secret Service API for secure password and credential storage
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive exception hierarchy for handling various error conditions in SecretStorage operations. All exceptions derive from the base SecretStorageException class, providing structured error handling for different failure scenarios.
SecretStorage defines a clear exception hierarchy for different types of errors that can occur during secret storage operations.
class SecretStorageException(Exception):
"""
Base exception class for all SecretStorage errors.
All other SecretStorage exceptions inherit from this class,
allowing for broad exception handling when needed.
"""
class SecretServiceNotAvailableException(SecretStorageException):
"""
Raised when the Secret Service API is not available.
This can occur when:
- D-Bus session bus is not running
- Secret Service daemon (GNOME Keyring, KWallet, etc.) is not installed
- Required environment variables are not set
- D-Bus connection cannot be established
"""
class LockedException(SecretStorageException):
"""
Raised when an operation cannot be performed because the collection or item is locked.
Operations that require unlocked collections/items:
- Reading secret data
- Creating/modifying items
- Deleting collections/items
- Setting labels and attributes
Use unlock() methods to resolve this condition.
"""
class ItemNotFoundException(SecretStorageException):
"""
Raised when an item or collection does not exist or has been deleted.
This can occur when:
- Accessing an item that was deleted by another process
- Using invalid D-Bus object paths
- Accessing collections that don't exist
- D-Bus objects that have become invalid
"""
class PromptDismissedException(ItemNotFoundException):
"""
Raised when a user dismisses an authentication or confirmation prompt.
This can occur during operations that require user interaction:
- Unlocking collections or items
- Creating new collections
- Deleting collections or items
- Any operation requiring user authentication
"""Basic Exception Handling:
import secretstorage
try:
connection = secretstorage.dbus_init()
collection = secretstorage.get_default_collection(connection)
item = collection.create_item("Test", {"app": "myapp"}, b"secret")
except secretstorage.SecretServiceNotAvailableException as e:
print(f"Secret service not available: {e}")
# Fallback to alternative storage method
except secretstorage.LockedException as e:
print(f"Collection is locked: {e}")
# Attempt to unlock or inform user
except secretstorage.PromptDismissedException as e:
print(f"User dismissed prompt: {e}")
# Handle user cancellation
except secretstorage.SecretStorageException as e:
print(f"General SecretStorage error: {e}")
# Handle any other SecretStorage-specific errorsHandling Locked Collections:
import secretstorage
connection = secretstorage.dbus_init()
collection = secretstorage.get_default_collection(connection)
try:
# Attempt operation that requires unlocked collection
secret = item.get_secret()
except secretstorage.LockedException:
# Try to unlock
try:
dismissed = collection.unlock()
if dismissed:
print("User dismissed unlock prompt")
# Handle user cancellation
else:
# Retry the operation
secret = item.get_secret()
except secretstorage.PromptDismissedException:
print("Failed to unlock - user dismissed prompt")
# Handle inability to unlockService Availability Check:
import secretstorage
try:
connection = secretstorage.dbus_init()
# Check if service is available before proceeding
if not secretstorage.check_service_availability(connection):
print("Secret service not available")
# Use alternative storage
else:
# Proceed with secret service operations
collection = secretstorage.get_default_collection(connection)
except secretstorage.SecretServiceNotAvailableException:
print("Cannot connect to D-Bus or secret service")
# Fallback to alternative storage methodRobust Item Creation:
import secretstorage
def store_secret_safely(label, attributes, secret_data):
"""Safely store a secret with comprehensive error handling."""
try:
connection = secretstorage.dbus_init()
collection = secretstorage.get_default_collection(connection)
# Ensure collection is unlocked
if collection.is_locked():
dismissed = collection.unlock()
if dismissed:
raise secretstorage.PromptDismissedException("Collection unlock dismissed")
# Create the item
item = collection.create_item(label, attributes, secret_data)
return item
except secretstorage.SecretServiceNotAvailableException:
print("Secret service unavailable - using alternative storage")
# Implement fallback storage mechanism
return None
except secretstorage.LockedException:
print("Cannot unlock collection")
return None
except secretstorage.PromptDismissedException:
print("User cancelled operation")
return None
except secretstorage.SecretStorageException as e:
print(f"Unexpected secret storage error: {e}")
return NoneItem Search with Error Handling:
import secretstorage
def find_secrets_safely(attributes):
"""Find secrets with proper error handling."""
try:
connection = secretstorage.dbus_init()
items = list(secretstorage.search_items(connection, attributes))
results = []
for item in items:
try:
# Check if we can access the item
if not item.is_locked():
secret = item.get_secret()
results.append({
'label': item.get_label(),
'attributes': item.get_attributes(),
'secret': secret
})
else:
# Attempt to unlock item
dismissed = item.unlock()
if not dismissed:
secret = item.get_secret()
results.append({
'label': item.get_label(),
'attributes': item.get_attributes(),
'secret': secret
})
except secretstorage.ItemNotFoundException:
# Item was deleted during iteration
continue
except secretstorage.LockedException:
# Item couldn't be unlocked
results.append({
'label': item.get_label(),
'attributes': item.get_attributes(),
'secret': None,
'locked': True
})
return results
except secretstorage.SecretServiceNotAvailableException:
print("Secret service not available")
return []
except secretstorage.SecretStorageException as e:
print(f"Error searching secrets: {e}")
return []dbus_init(), get_default_collection(), or any operation when the service becomes unavailableget_secret(), set_secret(), create_item(), delete(), or set_label() on locked collections/itemsunlock(), create_collection(), delete(), or any operation requiring user authentication# All exception classes inherit from Python's built-in Exception class
class Exception:
"""Base class for all Python exceptions."""Install with Tessl CLI
npx tessl i tessl/pypi-secretstorage