Jonathan Ballet avatar Jonathan Ballet committed d0f16fe

CLI tool tests now display less garbage on stdout

Comments (0)

Files changed (2)

 """Simple command line interface to get/set password from a keyring"""
 
 import getpass
-import optparse
+from optparse import OptionParser
 import sys
 
 import keyring
 import keyring.core
 
 
-def input_password(prompt):
-    """Ask for a password to the user.
+class CommandLineTool(object):
+    def __init__(self):
+        self.parser = OptionParser(usage="%prog [get|set] SERVICE USERNAME")
+        self.parser.add_option("-p", "--keyring-path",
+                               dest="keyring_path", default=None,
+                               help="Path to the keyring backend")
+        self.parser.add_option("-b", "--keyring-backend",
+                               dest="keyring_backend", default=None,
+                               help="Name of the keyring backend")
 
-    This mostly exists to ease the testing process.
-    """
+    def run(self, argv):
+        opts, args = self.parser.parse_args(argv)
 
-    return getpass.getpass(prompt)
+        try:
+            kind, service, username = args
+        except ValueError:
+            if len(args) == 0:
+                # Be nice with the user if he just tries to launch the tool
+                self.parser.print_help()
+                return 1
+            else:
+                self.parser.error("Wrong number of arguments")
 
+        if opts.keyring_backend is not None:
+            try:
+                backend = keyring.core.load_keyring(opts.keyring_path,
+                                                    opts.keyring_backend)
+                keyring.set_keyring(backend)
+            except Exception, e:
+                # Tons of things can go wrong here:
+                #   ImportError when using "fjkljfljkl"
+                #   AttributeError when using "os.path.bar"
+                #   TypeError when using "__builtins__.str"
+                # So, we play on the safe side, and catch everything.
+                self.parser.error("Unable to load specified keyring: %s" % e)
 
-def output_password(password):
-    """Output the password to the user.
 
-    This mostly exists to ease the testing process.
-    """
+        if kind == 'get':
+            password = keyring.get_password(service, username)
+            if password is None:
+                return 1
 
-    print password
+            self.output_password(password)
+            return 0
+
+        elif kind == 'set':
+            password = self.input_password("Password for '%s' in '%s': " %
+                                           (username, service))
+            keyring.set_password(service, username, password)
+            return 0
+
+        else:
+            self.parser.error("You can only 'get' or 'set' a password.")
+            pass
+
+    def input_password(self, prompt):
+        """Ask for a password to the user.
+
+        This mostly exists to ease the testing process.
+        """
+
+        return getpass.getpass(prompt)
+
+
+    def output_password(self, password):
+        """Output the password to the user.
+
+        This mostly exists to ease the testing process.
+        """
+
+        print password
 
 
 def main(argv=None):
     """Main command line interface."""
 
-    parser = optparse.OptionParser(usage="%prog [get|set] SERVICE USERNAME")
-    parser.add_option("-p", "--keyring-path", dest="keyring_path", default=None,
-                      help="Path to the keyring backend")
-    parser.add_option("-b", "--keyring-backend", dest="keyring_backend", default=None,
-                      help="Name of the keyring backend")
 
     if argv is None:
         argv = sys.argv[1:]
 
-    opts, args = parser.parse_args(argv)
-
-    try:
-        kind, service, username = args
-    except ValueError:
-        if len(args) == 0:
-            # Be nice with the user if he just tries to launch the tool
-            parser.print_help()
-            return 1
-        else:
-            parser.error("Wrong number of arguments")
-
-    if opts.keyring_backend is not None:
-        try:
-            backend = keyring.core.load_keyring(opts.keyring_path, opts.keyring_backend)
-            keyring.set_keyring(backend)
-        except Exception, e:
-            # Tons of things can go wrong here:
-            #   ImportError when using "fjkljfljkl"
-            #   AttributeError when using "os.path.bar"
-            #   TypeError when using "__builtins__.str"
-            # So, we play on the safe side, and catch everything.
-            parser.error("Unable to load specified keyring: %s" % e)
-
-
-    if kind == 'get':
-        password = keyring.get_password(service, username)
-        if password is None:
-            return 1
-
-        output_password(password)
-        return 0
-
-    elif kind == 'set':
-        password = input_password("Password for '%s' in '%s': " %
-                                  (username, service))
-        keyring.set_password(service, username, password)
-        return 0
-
-    else:
-        parser.error("You can only 'get' or 'set' a password.")
+    cli = CommandLineTool()
+    return cli.run(argv)
 
 
 if __name__ == '__main__':

keyring/tests/test_cli.py

 class CommandLineTestCase(unittest.TestCase):
     def setUp(self):
         self.old_keyring = keyring.get_keyring()
-        self.old_input_password = cli.input_password
-        self.old_output_password = cli.output_password
+
+        self.cli = cli.CommandLineTool()
+        self.cli.input_password = self.return_password
+        self.cli.output_password = self.save_password
+        self.cli.parser.error = self.mock_error
+        self.cli.parser.print_help = lambda: None
 
         keyring.set_keyring(SimpleKeyring())
+
         self.password = ""
         self.password_returned = None
-        cli.input_password = self.return_password
-        cli.output_password = self.save_password
+        self.last_error = None
 
     def tearDown(self):
         keyring.set_keyring(self.old_keyring)
-        cli.input_password = self.old_input_password
-        cli.output_password = self.old_output_password
 
     def return_password(self, *args, **kwargs):
         return self.password
     def save_password(self, password):
         self.password_returned = password
 
+    def mock_error(self, error):
+        self.last_error = error
+        raise SystemExit()
 
     def test_wrong_arguments(self):
-        self.assertEqual(1, cli.main([]))
+        self.assertEqual(1, self.cli.run([]))
 
-        self.assertRaises(SystemExit, cli.main, ["get"])
-        self.assertRaises(SystemExit, cli.main, ["get", "foo"])
-        self.assertRaises(SystemExit, cli.main, ["get", "foo", "bar", "baz"])
+        self.assertRaises(SystemExit, self.cli.run, ["get"])
+        self.assertRaises(SystemExit, self.cli.run, ["get", "foo"])
+        self.assertRaises(SystemExit, self.cli.run,
+                          ["get", "foo", "bar", "baz"])
 
-        self.assertRaises(SystemExit, cli.main, ["set"])
-        self.assertRaises(SystemExit, cli.main, ["set", "foo"])
-        self.assertRaises(SystemExit, cli.main, ["set", "foo", "bar", "baz"])
+        self.assertRaises(SystemExit, self.cli.run, ["set"])
+        self.assertRaises(SystemExit, self.cli.run, ["set", "foo"])
+        self.assertRaises(SystemExit, self.cli.run,
+                          ["set", "foo", "bar", "baz"])
 
-        self.assertRaises(SystemExit, cli.main, ["foo", "bar", "baz"])
+        self.assertRaises(SystemExit, self.cli.run, ["foo", "bar", "baz"])
 
     def test_get_unexistent_password(self):
-        self.assertEqual(1, cli.main(["get", "foo", "bar"]))
+        self.assertEqual(1, self.cli.run(["get", "foo", "bar"]))
         self.assertEqual(None, self.password_returned)
 
     def test_set_and_get_password(self):
         self.password = "plop"
-        self.assertEqual(0, cli.main(["set", "foo", "bar"]))
-        self.assertEqual(0, cli.main(["get", "foo", "bar"]))
+        self.assertEqual(0, self.cli.run(["set", "foo", "bar"]))
+        self.assertEqual(0, self.cli.run(["get", "foo", "bar"]))
         self.assertEqual("plop", self.password_returned)
 
     def test_load_builtin_backend(self):
-        self.assertEqual(1, cli.main(["get",
-                                      "-b", "keyring.backend.UncryptedFileKeyring",
-                                      "foo", "bar"]))
+        self.assertEqual(1, self.cli.run([
+            "get",
+            "-b", "keyring.backend.UncryptedFileKeyring",
+            "foo", "bar"]))
         backend = keyring.get_keyring()
         self.assertTrue(isinstance(backend,
                                    keyring.backend.UncryptedFileKeyring))
 
     def test_load_specific_backend_with_path(self):
         keyring_path = os.path.join(os.path.dirname(keyring.__file__), 'tests')
-        self.assertEqual(0, cli.main(["get",
-                                      "-b", "test_cli.FakeKeyring",
-                                      "-p", keyring_path,
-                                      "foo", "bar"]))
+        self.assertEqual(0, self.cli.run(["get",
+                                          "-b", "test_cli.FakeKeyring",
+                                          "-p", keyring_path,
+                                          "foo", "bar"]))
 
         backend = keyring.get_keyring()
         # Somehow, this doesn't work, because the full dotted name of the class
         self.assertEqual(FakeKeyring.PASSWORD, self.password_returned)
 
     def test_load_wrong_keyrings(self):
-        self.assertRaises(SystemExit, cli.main,
-                         ["get", "foo", "bar",
-                          "-b", "blablabla" # ImportError
-                         ])
-        self.assertRaises(SystemExit, cli.main,
-                         ["get", "foo", "bar",
-                          "-b", "os.path.blabla" # AttributeError
-                         ])
-        self.assertRaises(SystemExit, cli.main,
-                         ["get", "foo", "bar",
-                          "-b", "__builtin__.str" # TypeError
-                         ])
+        self.assertRaises(SystemExit, self.cli.run,
+                          ["get", "foo", "bar",
+                           "-b", "blablabla" # ImportError
+                          ])
+        self.assertRaises(SystemExit, self.cli.run,
+                          ["get", "foo", "bar",
+                           "-b", "os.path.blabla" # AttributeError
+                          ])
+        self.assertRaises(SystemExit, self.cli.run,
+                          ["get", "foo", "bar",
+                           "-b", "__builtin__.str" # TypeError
+                          ])
 
 
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.