[kupfer] Make 'keyring' module optional and make sure it never uses "crypted" keyring



commit 449230b1df3871952f3a69dc2dca7a117b7c3b7f
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Sun Jun 13 18:56:53 2010 +0200

    Make 'keyring' module optional and make sure it never uses "crypted" keyring
    
    Make sure we don't use the "CryptedFileKeyring", which will ask for
    keyring password etc etc; as fallback we use the uncrypted variant
    (Gnome / KWallet backends exist if security is desired).
    
    We at the same time move the UserNamePassword class to a better place
    and make the 'keyring' module optional (some plugins will need it).
    
    Launchpad bug: https://bugs.launchpad.net/kupfer/+bug/593319 Launchpad
    bug: https://bugs.launchpad.net/kupfer/+bug/576308

 README                                  |    4 +-
 kupfer/core/settings.py                 |   35 -------------------
 kupfer/plugin/gmail/__init__.py         |    2 +
 kupfer/plugin/google_picasa/__init__.py |    2 +
 kupfer/plugin/twitter/__init__.py       |    1 +
 kupfer/plugin_support.py                |   56 +++++++++++++++++++++++++++++-
 kupfer/ui/preferences.py                |    7 ++--
 7 files changed, 65 insertions(+), 42 deletions(-)
---
diff --git a/README b/README
index 2da653b..6fe6cf4 100644
--- a/README
+++ b/README
@@ -40,7 +40,6 @@ Kupfer requires Python 2.6 or later, and the following important libraries:
 * gtk python bindings, GTK+ version 2.16
 * glib python bindings (pygobject) 2.18
 * dbus python bindings
-* keyring python module
 
 Optional, but very recommended dependencies:
 
@@ -51,7 +50,8 @@ Optional, but very recommended dependencies:
   Gnome Terminal)
 * rst2man / python docutils  to build manpages
 * xml2po / gnome docutils  to install mallard help pages
-* python-keyring-gnome or python-keyring-kwallet
+* `keyring` python module, and optionally its extensions
+  python-keyring-gnome or python-keyring-kwallet
 
 Opportunistic dependencies
 
diff --git a/kupfer/core/settings.py b/kupfer/core/settings.py
index 35f2038..e09195d 100644
--- a/kupfer/core/settings.py
+++ b/kupfer/core/settings.py
@@ -7,7 +7,6 @@ import copy
 
 import glib
 import gobject
-import keyring
 
 from kupfer import config, pretty, scheduler
 
@@ -423,37 +422,3 @@ class ExtendedSetting(object):
 		plugin/key (string)'''
 		return None
 
-
-class UserNamePassword(ExtendedSetting):
-	''' Configuration type for storing username/password values.
-	Username is stored in Kupfer config, password in keyring '''
-	def __init__(self, obj=None):
-		ExtendedSetting.__init__(self)
-		self._configure_keyring()
-		self.username = None
-		self.password = None
-		if obj:
-			self.username = obj.username
-			self.password = obj.password
-
-	def __repr__(self):
-		return '<UserNamePassword "%s", %s>' % (self.username,
-		                                        bool(self.password))
-
-	@classmethod
-	def _configure_keyring(cls):
-		# Configure the fallback keyring's configuration file if used
-		kr = keyring.get_keyring()
-		if hasattr(kr, "file_path"):
-			kr.file_path = config.save_config_file("keyring.cfg")
-
-	def load(self, plugin_id, key, username):
-		self.password = keyring.get_password(plugin_id, username)
-		self.username = username
-
-	def save(self, plugin_id, key):
-		''' save @user_password - store password in keyring and return username
-		to save in standard configuration file '''
-		keyring.set_password(plugin_id, self.username, self.password)
-		return self.username
-
diff --git a/kupfer/plugin/gmail/__init__.py b/kupfer/plugin/gmail/__init__.py
index 3374a18..9aa7992 100644
--- a/kupfer/plugin/gmail/__init__.py
+++ b/kupfer/plugin/gmail/__init__.py
@@ -18,6 +18,8 @@ from kupfer.obj.grouping import ToplevelGroupingSource
 from kupfer.obj.contacts import ContactLeaf, EmailContact, email_from_leaf
 from kupfer import plugin_support, pretty, utils, icons, kupferstring
 
+plugin_support.check_keyring_support()
+
 __kupfer_settings__ = plugin_support.PluginSettings(
 	{
 		'key': 'userpass',
diff --git a/kupfer/plugin/google_picasa/__init__.py b/kupfer/plugin/google_picasa/__init__.py
index 7b8acdf..ea2c755 100644
--- a/kupfer/plugin/google_picasa/__init__.py
+++ b/kupfer/plugin/google_picasa/__init__.py
@@ -21,6 +21,8 @@ from kupfer import kupferstring
 from kupfer import utils
 from kupfer import task
 
+plugin_support.check_keyring_support()
+
 __kupfer_settings__ = plugin_support.PluginSettings(
 	{
 		'key': 'userpass',
diff --git a/kupfer/plugin/twitter/__init__.py b/kupfer/plugin/twitter/__init__.py
index a54a103..0c52e58 100644
--- a/kupfer/plugin/twitter/__init__.py
+++ b/kupfer/plugin/twitter/__init__.py
@@ -21,6 +21,7 @@ from kupfer.obj.grouping import ToplevelGroupingSource
 from kupfer.obj.contacts import ContactLeaf, NAME_KEY
 from kupfer.obj.special import PleaseConfigureLeaf
 
+plugin_support.check_keyring_support()
 
 __kupfer_settings__ = plugin_support.PluginSettings(
 	{
diff --git a/kupfer/plugin_support.py b/kupfer/plugin_support.py
index d494076..c8501b5 100644
--- a/kupfer/plugin_support.py
+++ b/kupfer/plugin_support.py
@@ -1,8 +1,14 @@
 import gobject
 
+try:
+	import keyring
+except ImportError:
+	keyring = None
+
+
 from kupfer import pretty
+from kupfer import config
 from kupfer.core import settings
-from kupfer.core.settings import UserNamePassword
 
 __all__ = [
 	"UserNamePassword",
@@ -124,5 +130,51 @@ def check_dbus_connection():
 	if not _has_dbus_connection:
 		raise ImportError(_("No D-Bus connection to desktop session"))
 
-
+def check_keyring_support():
+	"""
+	Check if the UserNamePassword class can be used,
+	else raise ImportError with an explanatory error message.
+	"""
+	import keyring
+
+class UserNamePassword (settings.ExtendedSetting):
+	''' Configuration type for storing username/password values.
+	Username is stored in Kupfer config, password in keyring '''
+	def __init__(self, obj=None):
+		settings.ExtendedSetting.__init__(self)
+		self._configure_keyring()
+		self.username = None
+		self.password = None
+		if obj:
+			self.username = obj.username
+			self.password = obj.password
+
+	def __repr__(self):
+		return '<UserNamePassword "%s", %s>' % (self.username,
+		                                        bool(self.password))
+
+	@classmethod
+	def _configure_keyring(cls):
+		# Configure the fallback keyring's configuration file if used
+		import keyring.backend
+		kr = keyring.get_keyring()
+		if hasattr(kr, "crypted_password"):
+			keyring.set_keyring(keyring.backend.UncryptedFileKeyring())
+			kr = keyring.get_keyring()
+		if hasattr(kr, "file_path"):
+			kr.file_path = config.save_config_file("keyring.cfg")
+
+	def load(self, plugin_id, key, username):
+		self.password = keyring.get_password(plugin_id, username)
+		self.username = username
+
+	def save(self, plugin_id, key):
+		''' save @user_password - store password in keyring and return username
+		to save in standard configuration file '''
+		keyring.set_password(plugin_id, self.username, self.password)
+		return self.username
+
+if not keyring:
+	class UserNamePassword (object):
+		pass
 
diff --git a/kupfer/ui/preferences.py b/kupfer/ui/preferences.py
index a12797c..167fa0a 100644
--- a/kupfer/ui/preferences.py
+++ b/kupfer/ui/preferences.py
@@ -15,6 +15,7 @@ from kupfer.core import settings, plugins, relevance, sources
 from kupfer.ui import keybindings
 from kupfer.ui.credentials_dialog import ask_user_credentials
 from kupfer.ui import getkey_dialog
+from kupfer import plugin_support
 
 # index in GtkNotebook
 PLUGIN_LIST_PAGE = 2
@@ -552,9 +553,9 @@ class PreferencesWindowController (pretty.OutputMixin):
 	def _get_plugin_credentials_callback(self, plugin_id, key):
 		def callback(widget):
 			setctl = settings.GetSettingsController()
-			val_type = settings.UserNamePassword
+			val_type = plugin_support.UserNamePassword
 			upass = setctl.get_plugin_config(plugin_id, key, val_type) \
-					or settings.UserNamePassword()
+					or plugin_support.UserNamePassword()
 			user_password = ask_user_credentials(upass.username, upass.password)
 			if user_password:
 				upass.username, upass.password = user_password
@@ -589,7 +590,7 @@ class PreferencesWindowController (pretty.OutputMixin):
 				hbox.set_tooltip_text(tooltip)
 			label = plugin_settings.get_label(setting)
 
-			if issubclass(typ, settings.UserNamePassword):
+			if issubclass(typ, plugin_support.UserNamePassword):
 				wid = gtk.Button(label or _("Set username and password"))
 				wid.connect("clicked", self._get_plugin_credentials_callback(
 						plugin_id, setting))



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]