From b310f00cb8610f7a3ceb252b4fae885dbe6382cb Mon Sep 17 00:00:00 2001 From: Guillaume Vincent Date: Wed, 20 Feb 2019 11:12:46 +0100 Subject: [PATCH] Format update --- cli/lesspass/__init__.py | 2 +- cli/lesspass/cli.py | 148 +++++++++++++++++++--------------- cli/lesspass/clipboard.py | 1 + cli/lesspass/core.py | 17 ++-- cli/lesspass/profile.py | 4 +- cli/lesspass/version.py | 2 +- cli/tests/test_interaction.py | 3 +- cli/tests/test_password_generation.py | 88 +++++++++++++------- cli/tests/test_validator.py | 59 -------------- 9 files changed, 158 insertions(+), 166 deletions(-) delete mode 100644 cli/tests/test_validator.py diff --git a/cli/lesspass/__init__.py b/cli/lesspass/__init__.py index 96e089d..982087d 100644 --- a/cli/lesspass/__init__.py +++ b/cli/lesspass/__init__.py @@ -1,2 +1,2 @@ name = "lesspass" -description = "Lesspass is a stateless password manager." \ No newline at end of file +description = "LessPass is a stateless password manager." \ No newline at end of file diff --git a/cli/lesspass/cli.py b/cli/lesspass/cli.py index eea2b93..1983c29 100644 --- a/cli/lesspass/cli.py +++ b/cli/lesspass/cli.py @@ -5,8 +5,7 @@ from lesspass import version from lesspass import name from lesspass import description -examples = \ -""" +EXAMPLES = """ examples: # no symbols lesspass site login masterpassword --no-symbols @@ -21,84 +20,107 @@ examples: LESSPASS_MASTER_PASSWORD="masterpassword" lesspass site login """ -copyright = \ -""" +COPYRIGHT = """ copyright: Copyright © 2018 Guillaume Vincent . License GPLv3: GNU GPL version 3 . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law """ + def parse_args(args): parser = argparse.ArgumentParser( - # we override usage here to match original help output - # and to indicate SITE as a required argument, either via - # cli or via the prompt flag usage="lesspass SITE [LOGIN] [MASTER_PASSWORD] [OPTIONS]", description=description, - epilog=examples+copyright, - formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument("-v", "--version", action="version", - version=version.__version__) - # technically this is required, but we can't require it here because - # the user can still provide this via --prompt - parser.add_argument("site", - nargs="?", - help="site used in the password generation. " + - "(required)") - parser.add_argument("login", nargs="?", - help="login used in the password generation." + - " Default to '' if not provided") + epilog=EXAMPLES + COPYRIGHT, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "-v", "--version", action="version", version=version.__version__ + ) + parser.add_argument("site", help="site used in the password generation (required)") + parser.add_argument( + "login", nargs="?", help="login used in the password generation. Default to ''." + ) parser.add_argument( "master_password", default=os.environ.get("LESSPASS_MASTER_PASSWORD", None), nargs="?", - help="master password used in password generation. Default " + - "to LESSPASS_MASTER_PASSWORD env variable or prompt." - ) - parser.add_argument("-L", "--length", default=16, type=int, - help="password length (default: 16, max: 35)") - parser.add_argument("-C", "--counter", default=1, type=int, - help="password counter (default: 1)") - parser.add_argument("-p", "--prompt", dest="prompt", - action="store_true", - help="prompt for values interactively") + help="master password used in password generation. Default to LESSPASS_MASTER_PASSWORD env variable or prompt.", + ) parser.add_argument( - "-c", "--copy", "--clipboard", dest="clipboard", action="store_true", - help="attempt to copy to password to clipboard" + "-L", + "--length", + default=16, + type=int, + help="password length (default: 16, max: 35)", + ) + parser.add_argument( + "-C", "--counter", default=1, type=int, help="password counter (default: 1)" + ) + parser.add_argument( + "-p", + "--prompt", + dest="prompt", + action="store_true", + help="prompt for values interactively", + ) + parser.add_argument( + "-c", + "--copy", + dest="clipboard", + action="store_true", + help="copy to password to clipboard", ) - lowercase_excl = parser.add_mutually_exclusive_group() - lowercase_excl.add_argument("-l", "--lowercase", - help="add lowercase in password", - dest="l", - action="store_true") - lowercase_excl.add_argument("--no-lowercase", - help="remove lowercase from password", - dest="nl", - action="store_true") - - uppercase_excl = parser.add_mutually_exclusive_group() - uppercase_excl.add_argument("-u", "--uppercase", dest="u", - help="add uppercase in password", - action="store_true") - uppercase_excl.add_argument("--no-uppercase", dest="nu", - help="remove uppercase from password", - action="store_true") + lowercase_group = parser.add_mutually_exclusive_group() + lowercase_group.add_argument( + "-l", + "--lowercase", + help="add lowercase in password", + dest="l", + action="store_true", + ) + lowercase_group.add_argument( + "--no-lowercase", + help="remove lowercase from password", + dest="nl", + action="store_true", + ) - digits_excl = parser.add_mutually_exclusive_group() + uppercase_group = parser.add_mutually_exclusive_group() + uppercase_group.add_argument( + "-u", + "--uppercase", + dest="u", + help="add uppercase in password", + action="store_true", + ) + uppercase_group.add_argument( + "--no-uppercase", + dest="nu", + help="remove uppercase from password", + action="store_true", + ) - digits_excl.add_argument("-d", "--digits", dest="d", - help="add digits in password", - action="store_true") - digits_excl.add_argument("--no-digits", dest="nd", - help="remove digits from password", - action="store_true") + digits_group = parser.add_mutually_exclusive_group() + digits_group.add_argument( + "-d", "--digits", dest="d", help="add digits in password", action="store_true" + ) + digits_group.add_argument( + "--no-digits", + dest="nd", + help="remove digits from password", + action="store_true", + ) - symbols_excl = parser.add_mutually_exclusive_group() - symbols_excl.add_argument("-s", "--symbols", dest="s", - help="add symbols in password", - action="store_true") - symbols_excl.add_argument("--no-symbols", dest="ns", - help="remove symbols from password", - action="store_true") + symbols_group = parser.add_mutually_exclusive_group() + symbols_group.add_argument( + "-s", "--symbols", dest="s", help="add symbols in password", action="store_true" + ) + symbols_group.add_argument( + "--no-symbols", + dest="ns", + help="remove symbols from password", + action="store_true", + ) return parser.parse_args(args) diff --git a/cli/lesspass/clipboard.py b/cli/lesspass/clipboard.py index 5cc9621..2d579bb 100644 --- a/cli/lesspass/clipboard.py +++ b/cli/lesspass/clipboard.py @@ -36,6 +36,7 @@ commands = { "xclip": ["xclip", "-selection", "clipboard"], } + def copy(text): command = get_system_copy_command() if command is None: diff --git a/cli/lesspass/core.py b/cli/lesspass/core.py index e5c3584..3afd054 100644 --- a/cli/lesspass/core.py +++ b/cli/lesspass/core.py @@ -12,11 +12,14 @@ from lesspass.clipboard import copy, get_system_copy_command signal.signal(signal.SIGINT, lambda s, f: sys.exit(0)) + def main(args=sys.argv[1:]): args = parse_args(args) if args.clipboard and not get_system_copy_command(): - print("ERROR To use the option -c (--copy) you need pbcopy " + - "on OSX, xsel or xclip on Linux, and clip on Windows") + print( + "ERROR To use the option -c (--copy) you need pbcopy " + + "on OSX, xsel or xclip on Linux, and clip on Windows" + ) sys.exit(3) if args.prompt: @@ -24,15 +27,12 @@ def main(args=sys.argv[1:]): args.login = getpass.getpass("Login: ") if not args.master_password: args.master_password = getpass.getpass("Master Password: ") - - # if by this point we don't have SITE or the master password, - # we should stop. + if not args.site: print("ERROR argument SITE is required but was not provided.") sys.exit(4) if not args.master_password: - print("ERROR argument MASTER_PASSWORD is required but " + - "was not provided") + print("ERROR argument MASTER_PASSWORD is required but was not provided") sys.exit(5) profile, master_password = create_profile(args) @@ -54,5 +54,6 @@ def main(args=sys.argv[1:]): else: print(generated_password) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/cli/lesspass/profile.py b/cli/lesspass/profile.py index 4800dd0..714e6d5 100644 --- a/cli/lesspass/profile.py +++ b/cli/lesspass/profile.py @@ -2,8 +2,8 @@ def create_profile(args): profile = { "lowercase": False if args.nl else True, "uppercase": False if args.nu else True, - "digits": False if args.nd else True, - "symbols": False if args.ns else True, + "digits": False if args.nd else True, + "symbols": False if args.ns else True, "length": args.length, "counter": args.counter, "site": args.site, diff --git a/cli/lesspass/version.py b/cli/lesspass/version.py index 9f62d76..b378fc6 100644 --- a/cli/lesspass/version.py +++ b/cli/lesspass/version.py @@ -1 +1 @@ -__version__ = '6.1.0' +__version__ = "7.0.0" diff --git a/cli/tests/test_interaction.py b/cli/tests/test_interaction.py index d687fb8..d8a686e 100644 --- a/cli/tests/test_interaction.py +++ b/cli/tests/test_interaction.py @@ -3,9 +3,10 @@ import pexpect import signal import time + class TestInteraction(unittest.TestCase): def test_keyboard_interrupt(self): - p = pexpect.spawn('python3 lesspass/core.py --prompt') + p = pexpect.spawn("python3 lesspass/core.py --prompt") p.expect("Site: ") p.kill(signal.SIGINT) p.expect(pexpect.EOF) diff --git a/cli/tests/test_password_generation.py b/cli/tests/test_password_generation.py index ace782c..39feece 100644 --- a/cli/tests/test_password_generation.py +++ b/cli/tests/test_password_generation.py @@ -89,10 +89,11 @@ class TestPassword(unittest.TestCase): "login": "contact@example.org", "counter": 1, } - master_password = 'password' + master_password = "password" self.assertEqual( - password._calc_entropy(password_profile, master_password), b'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e' + password._calc_entropy(password_profile, master_password), + b"dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e", ) def test_get_configured_rules_empty_when_no_rules_in_profile(self): @@ -108,67 +109,92 @@ class TestPassword(unittest.TestCase): "symbols": True, } - self.assertListEqual(password._get_configured_rules(password_profile), ['uppercase', 'symbols']) + self.assertListEqual( + password._get_configured_rules(password_profile), ["uppercase", "symbols"] + ) def test_get_set_of_characters_without_rule(self): - self.assertEqual(password._get_set_of_characters(), 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~') - + self.assertEqual( + password._get_set_of_characters(), + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ) + def test_get_set_of_characters_with_single_rule(self): - self.assertEqual(password._get_set_of_characters(["lowercase"]), "abcdefghijklmnopqrstuvwxyz") - self.assertEqual(password._get_set_of_characters(["uppercase"]), "ABCDEFGHIJKLMNOPQRSTUVWXYZ") + self.assertEqual( + password._get_set_of_characters(["lowercase"]), "abcdefghijklmnopqrstuvwxyz" + ) + self.assertEqual( + password._get_set_of_characters(["uppercase"]), "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + ) self.assertEqual(password._get_set_of_characters(["digits"]), "0123456789") - self.assertEqual(password._get_set_of_characters(["symbols"]), "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") - + self.assertEqual( + password._get_set_of_characters(["symbols"]), + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ) + def test_get_set_of_characters_with_several_rules(self): - self.assertEqual(password._get_set_of_characters(["lowercase", "digits"]), "abcdefghijklmnopqrstuvwxyz0123456789") + self.assertEqual( + password._get_set_of_characters(["lowercase", "digits"]), + "abcdefghijklmnopqrstuvwxyz0123456789", + ) def test_consume_entropy(self): - entropy = b'dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e' + entropy = b"dc33d431bce2b01182c613382483ccdb0e2f66482cbba5e9d07dab34acc7eb1e" - password_value, password_entropy = password._consume_entropy( - generated_password="", - quotient=int(entropy, 16), - set_of_characters="abcdefghijklmnopqrstuvwxyz0123456789", - max_length=12 + password_value, password_entropy = password._consume_entropy( + generated_password="", + quotient=int(entropy, 16), + set_of_characters="abcdefghijklmnopqrstuvwxyz0123456789", + max_length=12, ) - self.assertEqual(password_value, 'gsrwvjl3d0sn') - self.assertEqual(password_entropy, 21019920789038193790619410818194537836313158091882651458040) + self.assertEqual(password_value, "gsrwvjl3d0sn") + self.assertEqual( + password_entropy, + 21019920789038193790619410818194537836313158091882651458040, + ) def test_get_one_char_per_rule_without_rules(self): self.assertListEqual( - password._get_one_char_per_rule( entropy=21019920789038193790619410818194537836313158091882651458040, rules=[] ), - ['', 21019920789038193790619410818194537836313158091882651458040] + password._get_one_char_per_rule( + entropy=21019920789038193790619410818194537836313158091882651458040, + rules=[], + ), + ["", 21019920789038193790619410818194537836313158091882651458040], ) def test_get_one_char_per_rule_with_several_rules(self): self.assertListEqual( password._get_one_char_per_rule( - entropy=21019920789038193790619410818194537836313158091882651458040, - rules=['lowercase', 'digits'] + entropy=21019920789038193790619410818194537836313158091882651458040, + rules=["lowercase", "digits"], ), - ['a0', 80845849188608437656228503146902068601204454199548659454] + ["a0", 80845849188608437656228503146902068601204454199548659454], ) def test_insert_string_pseudo_randomly(self): self.assertEqual( password._insert_string_pseudo_randomly( - generated_password='gsrwvjl3d0sn', - entropy=80845849188608437656228503146902068601204454199548659454, - string='a0' - ), 'gsrwvjl03d0asn' + generated_password="gsrwvjl3d0sn", + entropy=80845849188608437656228503146902068601204454199548659454, + string="a0", + ), + "gsrwvjl03d0asn", ) def test_render_password(self): - password_profile = { + password_profile = { "site": "example.org", "login": "contact@example.org", "digits": True, "lowercase": True, "length": 14, - "counter": 1 + "counter": 1, } - master_password = 'password' + master_password = "password" entropy = password._calc_entropy(password_profile, master_password) - self.assertEqual(password._render_password(entropy, password_profile), 'gsrwvjl03d0asn') \ No newline at end of file + self.assertEqual( + password._render_password(entropy, password_profile), "gsrwvjl03d0asn" + ) + diff --git a/cli/tests/test_validator.py b/cli/tests/test_validator.py deleted file mode 100644 index 089def2..0000000 --- a/cli/tests/test_validator.py +++ /dev/null @@ -1,59 +0,0 @@ -# import unittest - -# from lesspass.cli import parse_args -# from lesspass.validator import validate_args - - -# class TestValidateArgs(unittest.TestCase): -# def test_validate_args_no_opposite_rules_lowercase(self): -# error, message = validate_args(parse_args(["site", "-l", "--no-lowercase"])) -# self.assertTrue(error) -# self.assertTrue( -# "Can't have -l (--lowercase) and --no-lowercase at the same time" in message -# ) - -# def test_validate_args_no_opposite_rules_uppercase(self): -# error, message = validate_args(parse_args(["site", "-u", "--no-uppercase"])) -# self.assertTrue(error) -# self.assertTrue( -# "Can't have -u (--uppercase) and --no-uppercase at the same time" in message -# ) - -# def test_validate_args_no_opposite_rules_digits(self): -# error, message = validate_args(parse_args(["site", "-d", "--no-digits"])) -# self.assertTrue(error) -# self.assertTrue( -# "Can't have -d (--digits) and --no-digits at the same time" in message -# ) - -# def test_validate_args_no_opposite_rules_symbols(self): -# error, message = validate_args(parse_args(["site", "-s", "--no-symbols"])) -# self.assertTrue(error) -# self.assertTrue( -# "Can't have -s (--symbols) and --no-symbols at the same time" in message -# ) - -# def test_validate_args_concat_errors(self): -# _, message = validate_args( -# parse_args(["site", "-u", "--no-uppercase", "-l", "--no-lowercase"]) -# ) -# self.assertTrue( -# "Can't have -l (--lowercase) and --no-lowercase at the same time" in message -# ) -# self.assertTrue( -# "Can't have -u (--uppercase) and --no-uppercase at the same time" in message -# ) - -# def test_validate_args_no_site(self): -# error, message = validate_args(parse_args([])) -# self.assertTrue(error) -# self.assertTrue( -# "SITE is a required argument" in message -# ) - -# def test_validate_args_site_optional_with_prompt(self): -# error, message = validate_args(parse_args(["--prompt"])) -# self.assertFalse(error) -# self.assertTrue( -# "SITE is a required argument" not in message -# )