Commits

Anonymous committed b72e818 Merge

Merging to include gdata-import-error

  • Participants
  • Parent commits b127c07, 5ea9ae4

Comments (0)

Files changed (1)

File keyring/backend.py

 import keyring.util.platform
 import keyring.util.loc_compat
 import keyring.py25compat
+from keyring import logger
 try:
     from keyczar import keyczar
 except ImportError:
             raise PasswordSetError("cancelled by user")
 
     def _safe_string(self, source, encoding='utf-8'):
-	"""Convert unicode to string as gnomekeyring barfs on unicode"""
+        """Convert unicode to string as gnomekeyring barfs on unicode"""
         if isinstance(source, unicode):
             return source.encode(encoding)
         return str(source)
         no_longer_locked, prompt = service_iface.Unlock(locked)
         assert prompt == "/"
         secrets = service_iface.GetSecrets(unlocked + locked, session,
-	                                   byte_arrays=True)
+                                       byte_arrays=True)
         for item_path, secret in secrets.iteritems():
-	    return unicode(secret[2])
+            return unicode(secret[2])
         return None
 
     def set_password(self, service, username, password):
                  collection=None, client=None,
                  can_create=True, input_getter=raw_input
                 ):
-        from gdata.docs.service import DocsService
-
         self.credential = credential
         self.crypter = crypter
         self.source = source
         self.input_getter = input_getter
         self._keyring_dict = None
 
-        if not client:
-            self._client = DocsService()
+        if client:
+            self.assign_client(client, source)
         else:
-            self._client = client
+            self._client_source = source
+        self._login_reqd = True
 
-        self._client.source = source
-        self._client.ssl = True
-        self._login_reqd = True
+
+    def assign_client(self, client, source):
+        self.__client = client
+        self.__client.source = source
+        self.__client.ssl = True
+
+    @property
+    def _client(self):
+        if hasattr(self, '__client'):
+            return self.__client
+
+        from gdata.docs.service import DocsService
+        self.assign_client(DocsService(), self._client_source)
+
+        return self.__client
 
     def supported(self):
         """Return if this keyring supports current environment:
 
     def _read(self):
         from gdata.docs.service import DocumentQuery
-        import gdata
         title_query = DocumentQuery(categories=[self.collection])
         title_query['title'] = self._get_doc_title()
         title_query['title-exact'] = 'true'
     """
     global _all_keyring
     if _all_keyring is None:
-        _all_keyring = [OSXKeychain(), GnomeKeyring(), KDEKWallet(),
-                        CryptedFileKeyring(), UncryptedFileKeyring(),
-                        Win32CryptoKeyring(), Win32CryptoRegistry(),
-                        WinVaultKeyring(), SecretServiceKeyring(),
-                        EnvironGoogleDocsKeyring(),
-                        UnencryptedPyfilesystemKeyring(),
-                        EnvironEncryptedPyfilesystemKeyring()]
+        _all_keyring = []
+        rings = [OSXKeychain, GnomeKeyring, KDEKWallet,
+                        CryptedFileKeyring, UncryptedFileKeyring,
+                        Win32CryptoKeyring, Win32CryptoRegistry,
+                        WinVaultKeyring, SecretServiceKeyring,
+                        EnvironGoogleDocsKeyring,
+                        UnencryptedPyfilesystemKeyring,
+                        EnvironEncryptedPyfilesystemKeyring]
+
+        # handle classes like GoogleDocsKeyring, which perform the same import in
+        # __init__ that it does in the supported method - triggering import
+        # errors when they shouldn't happen.
+
+        # In the long run this problem will have to be fixed in a more reliable
+        # way - you can't instantiate a keyring that does environment dependent
+        # things, and then check if it's supported. It's insane. I'd like to
+        # make either the __init__ methods do nothing platform specific, or
+        # make supported() a class method that doesn't reference a keyring
+        # object. Doing either of those in a way that doesn't break the API may
+        # be difficult, though.
+        for k in rings:
+            try:
+                k = k()
+            except ImportError, e:
+                logger.warning("ImportError while creating keyring %s: %s" % (k, str(e)))
+                continue
+            else:
+                if k.supported():
+                    _all_keyring.append(k)
+
     return _all_keyring