Skip to content

Commit

Permalink
Merge pull request #73 from QualiSystems/dev
Browse files Browse the repository at this point in the history
new version 3.3.2
  • Loading branch information
saklar13 committed Oct 11, 2018
2 parents df994e7 + e7404a5 commit 9789c48
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 36 deletions.
74 changes: 54 additions & 20 deletions cloudshell/cli/cli_service_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,63 @@
from cloudshell.cli.command_mode_helper import CommandModeHelper


class CommandModeContextManager(object):
"""
Context manager used to enter specific command mode
"""
class EnterCommandModeContextManager(object):

def __init__(self, cli_service, command_mode, logger):
"""Context manager used to enter specific command mode using CommandMode relations
in CommandMode.RELATIONS_DICT
:param CliServiceImpl cli_service:
:param CommandMode command_mode:
:param logging.Logger logger:
"""
:param cli_service:
:type cli_service: CliService
:param command_mode
:type command_mode: CommandMode
"""

self._cli_service = cli_service
self._command_mode = command_mode
self._logger = logger
self._previous_mode = None
self._previous_mode = cli_service.command_mode

def __enter__(self):
"""
:return:
:rtype: CliService
"""
""":rtype: CliServiceImpl"""

self._cli_service._change_mode(self._command_mode)
return self._cli_service

def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type: # if we catch an error throw it upper
return False

self._cli_service._change_mode(self._previous_mode)


class EnterDetachCommandModeContextManager(EnterCommandModeContextManager):

def __init__(self, cli_service, command_mode, logger):
"""Context manager used to enter specific command mode without using CommandMode relations
in CommandMode.RELATIONS_DICT"""

super(EnterDetachCommandModeContextManager, self).__init__(
cli_service, command_mode, logger)

if command_mode.parent_node is None:
command_mode.parent_node = self._previous_mode

def __enter__(self):
""":rtype: CliServiceImpl"""

self._command_mode.step_up(self._cli_service, self._logger)
return self._cli_service

def __exit__(self, type, value, traceback):
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type: # if we catch an error throw it upper
return False

self._command_mode.step_down(self._cli_service, self._logger)


CommandModeContextManager = EnterDetachCommandModeContextManager # Deprecated


class CliServiceImpl(CliService):
"""
Session wrapper, used to keep session mode and enter any child mode
Expand All @@ -59,14 +87,20 @@ def _initialize(self, requested_command_mode):
self._change_mode(requested_command_mode)

def enter_mode(self, command_mode):
"""
Enter child mode
"""Enter specified command mode
:param command_mode:
:type command_mode: CommandMode
:return:
:rtype: CommandModeContextManager
:return: context manager
:rtype: EnterCommandModeContextManager|EnterDetachCommandModeContextManager
"""
return CommandModeContextManager(self, command_mode, self._logger)

if command_mode.is_attached_command_mode():
context = EnterCommandModeContextManager
else:
context = EnterDetachCommandModeContextManager

return context(self, command_mode, self._logger)

def send_command(self, command, expected_string=None, action_map=None, error_map=None, logger=None,
remove_prompt=False, *args, **kwargs):
Expand Down
15 changes: 15 additions & 0 deletions cloudshell/cli/command_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,18 @@ def _initialize_exact_prompt(self, cli_service, logger):
raise Exception(self.__class__.__name__, 'Exact prompt is not matching the output')

return exact_prompt

@classmethod
def get_all_attached_command_modes(cls, relations_dict=None):
if relations_dict is None:
relations_dict = cls.RELATIONS_DICT

for key, val in relations_dict.items():
yield key

if isinstance(val, dict):
for key in cls.get_all_attached_command_modes(val):
yield key

def is_attached_command_mode(self):
return isinstance(self, tuple(self.get_all_attached_command_modes()))
103 changes: 88 additions & 15 deletions tests/cli/test_cli_service_impl.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,86 @@
from logging import Logger
from unittest import TestCase
from cloudshell.cli.cli_service_impl import CommandModeContextManager, CliServiceImpl
from mock import Mock, patch

from mock import Mock, patch, create_autospec, MagicMock

from cloudshell.cli.cli_service_impl import EnterCommandModeContextManager, CliServiceImpl, \
EnterDetachCommandModeContextManager
from cloudshell.cli.command_mode import CommandMode


class TestEnterCommandModeContextManager(TestCase):

class TestCommandModeContextManager(TestCase):
def setUp(self):
self._cli_service = Mock()
self._command_mode = Mock()
self._logger = Mock()
self._instance = CommandModeContextManager(self._cli_service, self._command_mode, self._logger)
self._cli_service = create_autospec(CliServiceImpl)
self._cli_service.session = MagicMock()
self._cli_service.command_mode = MagicMock()

self._command_mode = create_autospec(CommandMode)
self._logger = create_autospec(Logger)

self._instance = EnterCommandModeContextManager(
self._cli_service, self._command_mode, self._logger)

def test_init(self):
mandatory_attributes = ['_logger', '_previous_mode', '_cli_service', '_command_mode']
self.assertEqual(len(set(mandatory_attributes).difference(set(self._instance.__dict__.keys()))), 0)
self.assertItemsEqual(mandatory_attributes, self._instance.__dict__.keys())

def test_enter_call_change_mode(self):
cli_service = self._instance.__enter__()
self._cli_service._change_mode.assert_called_once_with(self._command_mode)
self.assertEqual(cli_service, self._cli_service)

def test_exit_call_change_mode(self):
self._instance.__exit__(None, None, None)
self._cli_service._change_mode.assert_called_once_with(self._cli_service.command_mode)

def test_exit_dont_handle_error_if_catch(self):
try:
with self._instance:
1/0
except ZeroDivisionError:
self._cli_service._change_mode.assert_called_once() # in enter command
else:
self.fail('context manager handle an error')


class TestEnterDetachCommandModeContextManager(TestCase):

def setUp(self):
self._cli_service = create_autospec(CliServiceImpl)
self._cli_service.session = MagicMock()
self._cli_service.command_mode = MagicMock()

self._command_mode = create_autospec(CommandMode)
self._command_mode.parent_node = None

self._logger = create_autospec(Logger)

self._instance = EnterDetachCommandModeContextManager(
self._cli_service, self._command_mode, self._logger)

def test_init(self):
mandatory_attributes = ['_logger', '_previous_mode', '_cli_service', '_command_mode']
self.assertItemsEqual(mandatory_attributes, self._instance.__dict__.keys())

def test_enter_call_step_up(self):
operations = self._instance.__enter__()
self._command_mode.step_up.assert_called_once_with(self._cli_service, self._logger)
self.assertEqual(operations, self._cli_service)
cli_service = self._instance.__enter__()
self._command_mode.step_up(self._cli_service, self._logger)
self.assertEqual(cli_service, self._cli_service)

def test_enter_call_step_down(self):
self._instance.__exit__(Mock(), Mock(), Mock())
def test_exit_call_step_down(self):
self._instance.__exit__(None, None, None)
self._command_mode.step_down.assert_called_once_with(self._cli_service, self._logger)

def test_exit_dont_handle_error_if_catch(self):
try:
with self._instance:
1/0
except ZeroDivisionError:
self._command_mode.step_down.assert_not_called()
else:
self.fail('context manager handle an error')


class TestCliOperationsImpl(TestCase):
def setUp(self):
Expand Down Expand Up @@ -55,12 +113,27 @@ def test_init_determined_mode_enter_actions_call(self):
def test_init_change_mod_call(self):
self._change_mode_func.assert_called_once_with(self._command_mode)

@patch("cloudshell.cli.cli_service_impl.CommandModeContextManager")
@patch("cloudshell.cli.cli_service_impl.EnterCommandModeContextManager")
def test_enter_mode(self, command_mode_context_manager):
command_mode_context_manager_instance = Mock()
command_mode_context_manager.return_value = command_mode_context_manager_instance
command_mode = Mock()
command_mode = create_autospec(CommandMode)
command_mode.is_attached_command_mode.return_value = True

instance = self._instance.enter_mode(command_mode)

command_mode_context_manager.assert_called_once_with(self._instance, command_mode, self._logger)
self.assertEqual(command_mode_context_manager_instance, instance)

@patch("cloudshell.cli.cli_service_impl.EnterDetachCommandModeContextManager")
def test_enter_detach_mode(self, command_mode_context_manager):
command_mode_context_manager_instance = Mock()
command_mode_context_manager.return_value = command_mode_context_manager_instance
command_mode = create_autospec(CommandMode)
command_mode.is_attached_command_mode.return_value = False

instance = self._instance.enter_mode(command_mode)

command_mode_context_manager.assert_called_once_with(self._instance, command_mode, self._logger)
self.assertEqual(command_mode_context_manager_instance, instance)

Expand Down
32 changes: 32 additions & 0 deletions tests/cli/test_command_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,35 @@ def test_step_down_set_mode(self):
self._command_mode.parent_node = parent_node
self._command_mode.step_down(cli_service, self._logger)
self.assertTrue(cli_service.command_mode == parent_node)

def test_get_all_attached_command_mode(self):
class CommandModeA(CommandMode):
pass

class CommandModeB(CommandMode):
pass

CommandMode.RELATIONS_DICT = {
CommandModeA: {
CommandModeB: {},
}
}

command_modes = CommandMode.get_all_attached_command_modes()

self.assertItemsEqual(command_modes, (CommandModeA, CommandModeB))

def test_is_attached_command_mode(self):
class CommandModeA(CommandMode):
pass

class CommandModeB(CommandMode):
pass

CommandMode.RELATIONS_DICT = {CommandModeA: {}}

command_mode_a = CommandModeA('')
command_mode_b = CommandModeB('')

self.assertTrue(command_mode_a.is_attached_command_mode())
self.assertFalse(command_mode_b.is_attached_command_mode())
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.3.1
3.3.2

0 comments on commit 9789c48

Please sign in to comment.