Skip to content

Commit

Permalink
implement multi commands feature closes #61
Browse files Browse the repository at this point in the history
  • Loading branch information
mogproject committed Oct 5, 2015
1 parent 0d845b6 commit ae05a39
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 8 deletions.
5 changes: 4 additions & 1 deletion src/easy_menu/setting/setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,10 @@ def build_config(config, is_root, depth):
return build_config(self._load_data(True, content), True, depth + 1)
else:
if isinstance(content, list):
content = [build_config(child, False, depth + 1) for child in content]
if all(isinstance(child, six.string_types) for child in content):
content = [string_util.to_unicode(cmd, self.encoding) for cmd in content]
else:
content = [build_config(child, False, depth + 1) for child in content]
elif is_leaf:
if is_root:
raise ConfigError(self.config_path, 'Root content must be list, not %s.' % t)
Expand Down
27 changes: 20 additions & 7 deletions src/easy_menu/view/terminal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import division, print_function, absolute_import, unicode_literals

import sys
import six

from easy_menu.util import string_util, term_util
from easy_menu.util.collection_util import get_single_item, get_single_key, get_single_value
Expand Down Expand Up @@ -199,7 +200,9 @@ def wait_input_menu(self, menu_items, offset, num_pages):

# check if it is a sub menu
if isinstance(command, list):
return lambda s, o: (s + [d], 0)
# check if it is a command list
if not all(isinstance(child, six.string_types) for child in command):
return lambda s, o: (s + [d], 0)

def f(s, o): # side effect only
self.execute_command(description, command)
Expand All @@ -216,7 +219,7 @@ def execute_command(self, description, command):
Confirm with prompt before executing command.
:param description: description string
:param command: command line string
:param command: command line string or list of command line string
:return: None
"""

Expand All @@ -232,12 +235,22 @@ def execute_command(self, description, command):

# run command
self._draw(self.get_before_execute(description))
return_code = self.executor.execute(
command, stdin=self._input, stdout=self._output, stderr=self._output, encoding=self.encoding)

if return_code == 130:
# maybe interrupted
self._print('\n')
# if command is string, convert to a list
if isinstance(command, six.string_types):
command = [command]

return_code = 0
for cmd in command:
return_code = self.executor.execute(
cmd, stdin=self._input, stdout=self._output, stderr=self._output, encoding=self.encoding)

if return_code == 130:
# maybe interrupted
self._print('\n')
# if a command fails, the successors will not run
if return_code != 0:
break

self._print(self.get_after_execute(return_code))
self.wait_input_char() # wait for any input
Expand Down
17 changes: 17 additions & 0 deletions tests/easy_menu/setting/test_setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ def test_lookup_config_not_found(self):
self.assertEqual(Setting(work_dir='/').lookup_config(), Setting(work_dir='/'))

def test_load_data(self):
self.maxDiff = None

with self.withAssertOutput('Reading file: tests/resources/minimum.yml\n', '') as (out, err):
self.assertEqual(
Setting(stdout=out, stderr=err)._load_data(False, 'tests/resources/minimum.yml'),
Expand Down Expand Up @@ -218,6 +220,21 @@ def test_load_data(self):
]
}
)
# multiple commands
with self.withAssertOutput('Reading file: tests/resources/multi_commands.yml\n', '') as (out, err):
self.assertEqual(Setting(stdout=out, stderr=err)._load_data(False, 'tests/resources/multi_commands.yml'),
{'Main Menu': [
{'Sub Menu 1': [
{'Menu 1': ['echo 1', 'echo 2']},
]},
{'Sub Menu 2': [
{'Sub Menu 3': [
{'Menu 3': 'echo 3'},
{'Menu 4': 'echo 4'}
]}, {'Menu 5': 'echo 5'}
]},
{'Menu 6': ['echo 1', 'echo 2', 'false', 'echo 3']}]}
)

@mock.patch('easy_menu.setting.setting.urlopen')
def test_load_data_http(self, urlopen_mock):
Expand Down
40 changes: 40 additions & 0 deletions tests/easy_menu/view/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,43 @@ def test_loop_sjis(self):
(6, "[INFO] Command started: echo 'あいうえお'"),
(6, "[INFO] Command ended with return code: 0"),
])

def test_loop_multiple_commands(self):
self.maxDiff = None

root_menu = {'Main Menu': [
{'Sub Menu 1': [
{'Menu 1': ['echo 1', 'echo 2']},
]},
{'Sub Menu 2': [
{'Sub Menu 3': [
{'Menu 3': 'echo 3'},
{'Menu 4': 'echo 4'}
]}, {'Menu 5': 'echo 5'}
]},
{'Menu 6': ['echo 6', 'echo 7', 'false', 'echo 8']}]
}

_in = FakeInput(''.join(['1', '.1yx', '0', '21.1yx', '0.0', '3yx', '0']))

# We use a temporary file due to capture the output of subprocess#call.
with self.withAssertOutputFile('tests/resources/expect/terminal_test_loop_multiple_commands.txt') as out:
t = Terminal(
root_menu,
'host', 'user', self.get_exec(), _input=_in, _output=out, encoding='utf-8', lang='en_US', width=80)
t.loop()

self.assertEqual(t.executor.logger.buffer, [
(6, '[INFO] Command started: echo 1'),
(6, '[INFO] Command ended with return code: 0'),
(6, '[INFO] Command started: echo 2'),
(6, '[INFO] Command ended with return code: 0'),
(6, '[INFO] Command started: echo 3'),
(6, '[INFO] Command ended with return code: 0'),
(6, '[INFO] Command started: echo 6'),
(6, '[INFO] Command ended with return code: 0'),
(6, '[INFO] Command started: echo 7'),
(6, '[INFO] Command ended with return code: 0'),
(6, '[INFO] Command started: false'),
(6, '[INFO] Command ended with return code: 1'),
])
137 changes: 137 additions & 0 deletions tests/resources/expect/terminal_test_loop_multiple_commands.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
Host: host User: user
================================================================================
Main Menu
--------------------------------------------------------------------------------
[1] | Go to Sub Menu 1
[2] | Go to Sub Menu 2
[3] | Go to Menu 6
------+-------------------------------------------------------------------------
[0] | Quit
================================================================================
Press menu number (0-3): Host: host User: user
================================================================================
Main Menu > Sub Menu 1
--------------------------------------------------------------------------------
[1] | Go to Menu 1
------+-------------------------------------------------------------------------
[0] | Return to Main Menu
================================================================================
Press menu number (0-1): Host: host User: user
================================================================================
Confirmation
--------------------------------------------------------------------------------
Would execute: Menu 1
================================================================================
Do you really want to execute? (y/n) [n]: Host: host User: user
================================================================================
Executing: Menu 1
--------------------------------------------------------------------------------
1
2
--------------------------------------------------------------------------------
Return code: 0
================================================================================
Press any key to continue...Host: host User: user
================================================================================
Main Menu > Sub Menu 1
--------------------------------------------------------------------------------
[1] | Go to Menu 1
------+-------------------------------------------------------------------------
[0] | Return to Main Menu
================================================================================
Press menu number (0-1): Host: host User: user
================================================================================
Main Menu
--------------------------------------------------------------------------------
[1] | Go to Sub Menu 1
[2] | Go to Sub Menu 2
[3] | Go to Menu 6
------+-------------------------------------------------------------------------
[0] | Quit
================================================================================
Press menu number (0-3): Host: host User: user
================================================================================
Main Menu > Sub Menu 2
--------------------------------------------------------------------------------
[1] | Go to Sub Menu 3
[2] | Menu 5
------+-------------------------------------------------------------------------
[0] | Return to Main Menu
================================================================================
Press menu number (0-2): Host: host User: user
================================================================================
Main Menu > Sub Menu 2 > Sub Menu 3
--------------------------------------------------------------------------------
[1] | Menu 3
[2] | Menu 4
------+-------------------------------------------------------------------------
[0] | Return to Sub Menu 2
================================================================================
Press menu number (0-2): Host: host User: user
================================================================================
Confirmation
--------------------------------------------------------------------------------
Would execute: Menu 3
================================================================================
Do you really want to execute? (y/n) [n]: Host: host User: user
================================================================================
Executing: Menu 3
--------------------------------------------------------------------------------
3
--------------------------------------------------------------------------------
Return code: 0
================================================================================
Press any key to continue...Host: host User: user
================================================================================
Main Menu > Sub Menu 2 > Sub Menu 3
--------------------------------------------------------------------------------
[1] | Menu 3
[2] | Menu 4
------+-------------------------------------------------------------------------
[0] | Return to Sub Menu 2
================================================================================
Press menu number (0-2): Host: host User: user
================================================================================
Main Menu > Sub Menu 2
--------------------------------------------------------------------------------
[1] | Go to Sub Menu 3
[2] | Menu 5
------+-------------------------------------------------------------------------
[0] | Return to Main Menu
================================================================================
Press menu number (0-2): Host: host User: user
================================================================================
Main Menu
--------------------------------------------------------------------------------
[1] | Go to Sub Menu 1
[2] | Go to Sub Menu 2
[3] | Go to Menu 6
------+-------------------------------------------------------------------------
[0] | Quit
================================================================================
Press menu number (0-3): Host: host User: user
================================================================================
Confirmation
--------------------------------------------------------------------------------
Would execute: Menu 6
================================================================================
Do you really want to execute? (y/n) [n]: Host: host User: user
================================================================================
Executing: Menu 6
--------------------------------------------------------------------------------
6
7
--------------------------------------------------------------------------------
Return code: 1
================================================================================
Press any key to continue...Host: host User: user
================================================================================
Main Menu
--------------------------------------------------------------------------------
[1] | Go to Sub Menu 1
[2] | Go to Sub Menu 2
[3] | Go to Menu 6
------+-------------------------------------------------------------------------
[0] | Quit
================================================================================
Press menu number (0-3):
17 changes: 17 additions & 0 deletions tests/resources/multi_commands.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
Main Menu:
- Sub Menu 1:
- Menu 1:
- echo 1
- echo 2
- Sub Menu 2:
- Sub Menu 3:
- Menu 3: echo 3
- Menu 4: echo 4
- Menu 5: echo 5
- Menu 6:
- echo 1
- echo 2
- "false"
- echo 3

0 comments on commit ae05a39

Please sign in to comment.