Commits

Jonathan Ballet committed e17efe6 Merge

Merged with tip

  • Participants
  • Parent commits 864ed34, 711517d

Comments (0)

Files changed (7)

+buildout = [svn]svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
+123006 buildout
-.. -*- restructuredtext -*-
-
 =======================================
 Installing and Using Python Keyring Lib
 =======================================

File keyring/backend.py

     def set_password(self, service, username, password):
         """Set password for the username of the service
         """
-        raise PasswordSetError()
+        raise PasswordSetError("reason")
 
 class _ExtensionKeyring(KeyringBackend):
     """_ExtensionKeyring is a adaptor class for the platform related keyring
         """
         try:
             self.keyring_impl.password_set(service, username, password)
-        except OSError:
-            raise PasswordSetError()
+        except OSError, e:
+            raise PasswordSetError(e.message)
 
 class OSXKeychain(_ExtensionKeyring):
     """Mac OSX Keychain"""
                 None, None, None, None, 0, password)
         except gnomekeyring.CancelledError:
             # The user pressed "Cancel" when prompted to unlock their keyring.
-            raise PasswordSetError()
+            raise PasswordSetError("cancelled by user")
 
 kwallet = None
 
             self.pywintypes = pywintypes
         except ImportError:
             self.win32cred = None
-    
+
     def supported(self):
         '''Default Windows backend, when it is available
         '''
             return 1
         else:
             return 0
-    
+
     def get_password(self, service, username):
         try:
-            blob = self.win32cred.CredRead(Type=self.win32cred.CRED_TYPE_GENERIC, 
+            blob = self.win32cred.CredRead(Type=self.win32cred.CRED_TYPE_GENERIC,
                                            TargetName=service)['CredentialBlob']
         except self.pywintypes.error, e:
             if e[:2] == (1168, 'CredRead'):
                 return None
             raise
         return blob.decode("utf16")
-    
+
     def set_password(self, service, username, password):
-        credential = dict(Type=self.win32cred.CRED_TYPE_GENERIC, 
+        credential = dict(Type=self.win32cred.CRED_TYPE_GENERIC,
                           TargetName=service,
                           UserName=username,
                           CredentialBlob=unicode(password),
                           Persist=self.win32cred.CRED_PERSIST_ENTERPRISE)
         self.win32cred.CredWrite(credential, 0)
 
+    def delete_password(self, service, username):
+        self.win32cred.CredDelete(
+            Type=self.win32cred.CRED_TYPE_GENERIC,
+            TargetName=service,
+        )
 
 class Win32CryptoRegistry(KeyringBackend):
     """Win32CryptoRegistry is a keyring which use Windows CryptAPI to encrypt

File keyring/tests/test_backend.py

 @contextlib.contextmanager
 def NoNoneDictMutator(destination, **changes):
     """Helper context manager to make and unmake changes to a dict.
-    
+
     A None is not a valid value for the destination, and so means that the
     associated name should be removed."""
     original = {}
 
     def setUp(self):
         self.keyring = self.init_keyring()
+        self.credentials_created = set()
+
+    def set_password(self, service, username, password):
+        # set the password and save the result so the test runner can clean
+        #  up after if necessary.
+        self.keyring.set_password(service, username, password)
+        self.credentials_created.add((service, username))
 
     def check_set_get(self, service, username, password):
         keyring = self.keyring
 
-        # for the non-exsit password
+        # for the non-existent password
         self.assertEqual(keyring.get_password(service, username), None)
 
         # common usage
-        keyring.set_password(service, username, password)
+        self.set_password(service, username, password)
         self.assertEqual(keyring.get_password(service, username), password)
 
         # for the empty password
-        keyring.set_password(service, username, "")
+        self.set_password(service, username, "")
         self.assertEqual(keyring.get_password(service, username), "")
 
     def test_password_set_get(self):
         service = random_string(20, DIFFICULT_CHARS)
         self.check_set_get(service, username, password)
 
+    def test_different_user(self):
+        """
+        Issue #47 reports that WinVault isn't storing passwords for
+        multiple users. This test exercises that test for each of the
+        backends.
+        """
+
+        keyring = self.keyring
+        self.set_password('service1', 'user1', 'password1')
+        self.set_password('service1', 'user2', 'password2')
+        self.assertEqual(keyring.get_password('service1', 'user1'),
+            'password1')
+        self.assertEqual(keyring.get_password('service1', 'user2'),
+            'password2')
+        self.set_password('service2', 'user3', 'password3')
+        self.assertEqual(keyring.get_password('service1', 'user1'),
+            'password1')
 
 @unittest.skipUnless(is_osx_keychain_supported(),
                      "Need OS X")
 
 class FauxQtGui(object):
     """A fake module-like object used in testing the open_kwallet function."""
-    
+
     class qApp:
         @staticmethod
         def instance():
     __test__ = False
 
     def setUp(self):
+        super(FileKeyringTestCase, self).setUp()
         self.keyring = self.init_keyring()
         self.keyring.file_path = self.tmp_keyring_file = tempfile.mktemp()
 
         return keyring.backend.Win32CryptoKeyring()
 
 
+class WinVaultKeyringTestCase(BackendBasicTestCase):
+
+    def tearDown(self):
+        # clean up any credentials created
+        for cred in self.credentials_created:
+            try:
+                self.keyring.delete_password(*cred)
+            except Exception, e:
+                print >> sys.stderr, e
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(OSXKeychainTestCase))

File keyring/util/escape.py

 
 import string, re
 
-LEGAL_CHARS = string.letters + string.digits
+LEGAL_CHARS = (
+    getattr(string, 'letters', None) # Python 2
+    or getattr(string, 'ascii_letters') # Python 3
+) + string.digits
 ESCAPE_CHAR = "_"
 
 def escape(value):
-    """Escapes given value so the result consists of alphanumeric chars and underscore
-    only, and alphanumeric chars are preserved"""
+    """Escapes given value so the result consists of alphanumeric chars and
+    ESCAPE_CHAR only"""
     def escape_char(c, legal = LEGAL_CHARS):
         # Single char escape. Either normal char, or _<hexcode>
         if c in legal:
 """
 
 import sys, os, subprocess
-from distutils.core import setup, Extension
 from distutils.version import StrictVersion
 
 def runcmd(cmd, env):
     out, err = p.communicate()
     return out, err
 
-if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
-    # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
-    # distutils.sysconfig
-    version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()[0]
-    # Also parse only first digit, because 3.2.1 can't be parsed nicely
-    if (version.startswith('Xcode') and
-        StrictVersion(version.split()[1]) >= StrictVersion('4.0')):
-        os.environ['ARCHFLAGS'] = ''
+setup_params = dict(
+    name = 'keyring',
+    version = "0.7",
+    description = "Store and access your passwords safely.",
+    url = "http://home.python-keyring.org/",
+    keywords = "keyring Keychain GnomeKeyring Kwallet password storage",
+    maintainer = "Kang Zhang",
+    maintainer_email = "jobo.zh@gmail.com",
+    license="PSF",
+    long_description = open('README').read() + open('CHANGES.txt').read(),
+    platforms = ["Many"],
+    packages = ['keyring', 'keyring.tests', 'keyring.util',
+                'keyring.backends'],
+)
 
-setup(name = 'keyring',
-      version = "0.7",
-      description = "Store and access your passwords safely.",
-      url = "http://home.python-keyring.org/",
-      keywords = "keyring Keychain GnomeKeyring Kwallet password storage",
-      maintainer = "Kang Zhang",
-      maintainer_email = "jobo.zh@gmail.com",
-      license="PSF",
-      long_description = open('README').read() + open('CHANGES.txt').read(),
-      platforms = ["Many"],
-      packages = ['keyring', 'keyring.tests', 'keyring.util',
-                  'keyring.backends'],
+if sys.version_info >= (3,0):
+    setup_params.update(
+        use_2to3=True,
     )
 
+if __name__ == '__main__':
+    try:
+        from setuptools import setup
+    except ImportError:
+        from distutils.core import setup
+    setup(**setup_params)