From eab2f4b0566b4c76db661cbfa99a56a6bf8d6541 Mon Sep 17 00:00:00 2001 From: philippeitis <33013301+philippeitis@users.noreply.github.com> Date: Sun, 8 Mar 2020 13:20:38 -0700 Subject: [PATCH 1/5] Move core magic() logic into seperate function for testability, minor tweaks. We only care about the command when testing magic() - by moving that out, we can easily test the command. I modified the code to return a boolean signalling that the command is valid, and the command itself to maintain the original functionality. I also made some small tweaks (removed a list() call, fixed a possible bug with no arguments., moved magic_dict instantiation past the fast path checks to avoid making a dict if not needed.) --- jc/cli.py | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/jc/cli.py b/jc/cli.py index a5b1af01..aebf829b 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -183,18 +183,15 @@ def json_out(data, pretty=False): print(json.dumps(data)) -def magic(): - """Parse with magic syntax: jc -p ls -al""" +def generate_magic_command(): + """ + Returns a tuple with a boolean and a command, where the boolean signifies that + the command is valid, and the command is either a command string or None. + """ + + # Parse with magic syntax: jc -p ls -al if len(sys.argv) <= 1 or sys.argv[1].startswith('--'): - return - - magic_dict = {} - parser_info = about_jc()['parsers'] - - # Create a dictionary of magic_commands to their respective parsers. - for entry in parser_info: - # Update the dict with all of the magic commands for this parser, if they exist. - magic_dict.update({mc: entry['argument'] for mc in entry.get('magic_commands', [])}) + return False, None # correctly parse escape characters and spaces with shlex args_given = " ".join(map(shlex.quote, sys.argv[1:])).split() @@ -202,10 +199,10 @@ def magic(): # find the options popped = 0 - for i, arg in list(enumerate(args_given)): + for i, arg in enumerate(args_given): # parser found - use standard syntax if arg.startswith('--'): - return + return False, None # option found - populate option list elif arg.startswith('-'): @@ -218,7 +215,15 @@ def magic(): # all options popped and no command found - for case like 'jc -a' if len(args_given) == 0: - return + return False, None + + magic_dict = {} + parser_info = about_jc()['parsers'] + + # Create a dictionary of magic_commands to their respective parsers. + for entry in parser_info: + # Update the dict with all of the magic commands for this parser, if they exist. + magic_dict.update({mc: entry['argument'] for mc in entry.get('magic_commands', [])}) # find the command and parser one_word_command = args_given[0] @@ -230,11 +235,19 @@ def magic(): # construct a new command line using the standard syntax: COMMAND | jc --PARSER -OPTIONS run_command = ' '.join(args_given) if found_parser: - cmd_options = '-' + ''.join(options) if options else '' - whole_command = ' '.join([run_command, '|', 'jc', found_parser, cmd_options]) - os.system(whole_command) - exit() + cmd_options = ('-' + ''.join(options)) if options else '' + return True, ' '.join([run_command, '|', 'jc', found_parser, cmd_options]) + else: + return False, run_command + +def magic(): + valid_command, run_command = generate_magic_command() + if valid_command: + os.system(run_command) + exit() + elif run_command is None: + return else: helptext(f'parser not found for "{run_command}"') sys.exit(1) @@ -293,7 +306,8 @@ def main(): found = True break except Exception: - jc.utils.error_message(f'{parser_name} parser could not parse the input data. Did you use the correct parser?\n For details use the -d option.') + jc.utils.error_message( + f'{parser_name} parser could not parse the input data. Did you use the correct parser?\n For details use the -d option.') sys.exit(1) if not found: From a032ae56ae7d247e00415267b65b2a8b80a3302e Mon Sep 17 00:00:00 2001 From: philippeitis <33013301+philippeitis@users.noreply.github.com> Date: Sun, 8 Mar 2020 13:26:15 -0700 Subject: [PATCH 2/5] Pass args to generate_magic_command() to allow testing. --- jc/cli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jc/cli.py b/jc/cli.py index aebf829b..fda0d106 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -183,18 +183,18 @@ def json_out(data, pretty=False): print(json.dumps(data)) -def generate_magic_command(): +def generate_magic_command(args): """ Returns a tuple with a boolean and a command, where the boolean signifies that the command is valid, and the command is either a command string or None. """ # Parse with magic syntax: jc -p ls -al - if len(sys.argv) <= 1 or sys.argv[1].startswith('--'): + if len(args) <= 1 or args[1].startswith('--'): return False, None # correctly parse escape characters and spaces with shlex - args_given = " ".join(map(shlex.quote, sys.argv[1:])).split() + args_given = " ".join(map(shlex.quote, args[1:])).split() options = [] # find the options @@ -242,7 +242,7 @@ def generate_magic_command(): def magic(): - valid_command, run_command = generate_magic_command() + valid_command, run_command = generate_magic_command(sys.argv) if valid_command: os.system(run_command) exit() From 17b6efe82e6a558353b011c543489eaaf3a6d3ac Mon Sep 17 00:00:00 2001 From: philippeitis <33013301+philippeitis@users.noreply.github.com> Date: Sun, 8 Mar 2020 13:35:01 -0700 Subject: [PATCH 3/5] Create basic tests for generate_magic_commands() --- tests/test_cli.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/test_cli.py diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 00000000..69542f6f --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,14 @@ +import os +import unittest +import jc.cli + + +class MyTests(unittest.TestCase): + def test_cli(self): + commands = { + "jc -p systemctl list-sockets": "systemctl list-sockets | jc --systemctl-ls -p", + "jc -p systemctl list-unit-files": "systemctl list-unit-files | jc --systemctl-luf -p", + } + + for command, expected_command in commands.items(): + self.assertEquals(jc.cli.generate_magic_command(command.split(" "))[1], expected_command) From 56053103625af6fb7fa749fc5bc3dbdc62fc223c Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 8 Mar 2020 14:02:54 -0700 Subject: [PATCH 4/5] added tests, removed os import, changed to 'assertEqual' --- tests/test_cli.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 69542f6f..fdd768da 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,3 @@ -import os import unittest import jc.cli @@ -6,9 +5,17 @@ import jc.cli class MyTests(unittest.TestCase): def test_cli(self): commands = { - "jc -p systemctl list-sockets": "systemctl list-sockets | jc --systemctl-ls -p", - "jc -p systemctl list-unit-files": "systemctl list-unit-files | jc --systemctl-luf -p", + 'jc -p systemctl list-sockets': 'systemctl list-sockets | jc --systemctl-ls -p', + 'jc -p systemctl list-unit-files': 'systemctl list-unit-files | jc --systemctl-luf -p', + 'jc -p pip list': 'pip list | jc --pip-list -p', + 'jc -p pip3 list': 'pip3 list | jc --pip-list -p', + 'jc -p pip show jc': 'pip show jc | jc --pip-show -p', + 'jc -p pip3 show jc': 'pip3 show jc | jc --pip-show -p', + 'jc -prd last': 'last | jc --last -prd', + 'jc -prd lastb': 'lastb | jc --last -prd', + 'jc -p nonexistent command': 'nonexistent command', + 'jc -ap': None } for command, expected_command in commands.items(): - self.assertEquals(jc.cli.generate_magic_command(command.split(" "))[1], expected_command) + self.assertEqual(jc.cli.generate_magic_command(command.split(' '))[1], expected_command) From c3d7d7db12d4870fc4499e0e3445d85ae89f2aea Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 8 Mar 2020 14:03:08 -0700 Subject: [PATCH 5/5] removed whitespace --- jc/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index fda0d106..7f16cf0e 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -188,7 +188,7 @@ def generate_magic_command(args): Returns a tuple with a boolean and a command, where the boolean signifies that the command is valid, and the command is either a command string or None. """ - + # Parse with magic syntax: jc -p ls -al if len(args) <= 1 or args[1].startswith('--'): return False, None