فهرست منبع

review argument passed to neuron from order

nico 8 سال پیش
والد
کامیت
dde98f8871
2فایلهای تغییر یافته به همراه203 افزوده شده و 54 حذف شده
  1. 124 23
      Tests/test_neuron_launcher.py
  2. 79 31
      kalliope/core/NeuronLauncher.py

+ 124 - 23
Tests/test_neuron_launcher.py

@@ -2,7 +2,7 @@ import unittest
 import mock
 
 from kalliope.core.Models.Resources import Resources
-from kalliope.core.NeuronLauncher import NeuronLauncher
+from kalliope.core.NeuronLauncher import NeuronLauncher, NeuronParameterNotAvailable
 from kalliope.core.ConfigurationManager import SettingLoader
 
 from kalliope.core.Models.Neuron import Neuron
@@ -41,38 +41,29 @@ class TestNeuronLauncher(unittest.TestCase):
         """
 
         with mock.patch("kalliope.core.NeuronLauncher.launch_neuron") as mock_launch_neuron_method:
-            # Assert to the neuron is launched
+            # Assert to the neuron is launched with not parameter from order
             neuron1 = Neuron(name='neurone1', parameters={'var1': 'val1'})
-            params = {
-                'param1':'parval1'
-            }
-            NeuronLauncher.start_neuron(neuron=neuron1,
-                                        parameters_dict=params)
+
+            NeuronLauncher.start_neuron(neuron=neuron1)
             mock_launch_neuron_method.assert_called_with(neuron1)
             mock_launch_neuron_method.reset_mock()
 
             # Assert the params are well passed to the neuron
-            neuron2 = Neuron(name='neurone2', parameters={'var2': 'val2', 'args': ['arg1', 'arg2']})
+            neuron2 = Neuron(name='neurone2', parameters={'var2': 'val2', 'var3': "{{ var3 }}"})
             params = {
-                'arg1':'argval1',
-                'arg2':'argval2'
+                'var3': 'value3'
             }
             NeuronLauncher.start_neuron(neuron=neuron2,
                                         parameters_dict=params)
-            neuron2_params = Neuron(name='neurone2',
-                                    parameters={'var2': 'val2',
-                                                'args': ['arg1', 'arg2'],
-                                                'arg1':'argval1',
-                                                'arg2':'argval2'}
-                                    )
+            neuron2_params = Neuron(name='neurone2', parameters={'var2': 'val2', 'var3': 'value3'})
+
             mock_launch_neuron_method.assert_called_with(neuron2_params)
             mock_launch_neuron_method.reset_mock()
 
             # Assert the Neuron is not started when missing args
-            neuron3 = Neuron(name='neurone3', parameters={'var3': 'val3', 'args': ['arg3', 'arg4']})
+            neuron3 = Neuron(name='neurone3', parameters={'var3': 'val3', 'var4': '{{val4}}'})
             params = {
-                'arg1': 'argval1',
-                'arg2': 'argval2'
+                'not_exist': 'test'
             }
             NeuronLauncher.start_neuron(neuron=neuron3,
                                         parameters_dict=params)
@@ -80,11 +71,121 @@ class TestNeuronLauncher(unittest.TestCase):
             mock_launch_neuron_method.reset_mock()
 
             # Assert no neuron is launched when waiting for args and none are given
-            neuron4 = Neuron(name='neurone4', parameters={'var4': 'val4', 'args': ['arg5', 'arg6']})
-            params = {}
-            NeuronLauncher.start_neuron(neuron=neuron4,
-                                        parameters_dict=params)
+            neuron4 = Neuron(name='neurone4', parameters={'var5': 'val5', 'var6': '{{val6}}'})
+
+            NeuronLauncher.start_neuron(neuron=neuron4)
             mock_launch_neuron_method.assert_not_called()
             mock_launch_neuron_method.reset_mock()
 
+    def test_replace_brackets_by_loaded_parameter(self):
+        # -------------------
+        # test with string
+        # -------------------
+        # the target value to replace is present in the loaded parameter dict
+        neuron_parameters = {
+            "param1": "this is a value {{ replaced }}"
+        }
+
+        loaded_parameters = {
+            "replaced": "replaced successfully"
+        }
+
+        expected_result = {
+            "param1": "this is a value replaced successfully"
+        }
+
+        self.assertEqual(expected_result, NeuronLauncher._replace_brackets_by_loaded_parameter(neuron_parameters,
+                                                                                               loaded_parameters))
+
+        # the target value to replace is NOT present in the loaded parameter dict
+        neuron_parameters = {
+            "param1": "this is a value {{ replaced }}"
+        }
+
+        loaded_parameters = {
+            "not_exist": "replaced successfully"
+        }
+
+        with self.assertRaises(NeuronParameterNotAvailable):
+            NeuronLauncher._replace_brackets_by_loaded_parameter(neuron_parameters, loaded_parameters)
+
+        # one parameter doesn't contains bracket, the other one do
+        neuron_parameters = {
+            "param1": "this is a value {{ replaced }}",
+            "param2": "value"
+        }
+
+        loaded_parameters = {
+            "replaced": "replaced successfully"
+        }
+
+        expected_result = {
+            "param1": "this is a value replaced successfully",
+            "param2": "value"
+        }
+
+        self.assertEqual(expected_result, NeuronLauncher._replace_brackets_by_loaded_parameter(neuron_parameters,
+                                                                                               loaded_parameters))
+
+        # parameters are integer or boolean
+        neuron_parameters = {
+            "param1": 1,
+            "param2": True
+        }
+
+        loaded_parameters = {
+            "replaced": "replaced successfully"
+        }
+
+        expected_result = {
+            "param1": 1,
+            "param2": True
+        }
+
+        self.assertEqual(expected_result, NeuronLauncher._replace_brackets_by_loaded_parameter(neuron_parameters,
+                                                                                               loaded_parameters))
+
+    def test_parameters_are_available_in_loaded_parameters(self):
+        # the parameter in bracket is available in the dict
+        string_parameters = "this is a {{ parameter1 }}"
+        loaded_parameters = {"parameter1": "value"}
+
+        self.assertTrue(NeuronLauncher.neuron_parameters_are_available_in_loaded_parameters(string_parameters,
+                                                                                            loaded_parameters))
+
+        # the parameter in bracket is NOT available in the dict
+        string_parameters = "this is a {{ parameter1 }}"
+        loaded_parameters = {"parameter2": "value"}
+
+        self.assertFalse(NeuronLauncher.neuron_parameters_are_available_in_loaded_parameters(string_parameters,
+                                                                                             loaded_parameters))
+
+        # the string_parameters doesn't contains bracket in bracket is available in the dict
+        string_parameters = "this is a {{ parameter1 }}"
+        loaded_parameters = {"parameter1": "value"}
+
+        self.assertTrue(NeuronLauncher.neuron_parameters_are_available_in_loaded_parameters(string_parameters,
+                                                                                            loaded_parameters))
+
+        # the string_parameters contains 2 parameters available in the dict
+        string_parameters = "this is a {{ parameter1 }} and this is {{ parameter2 }}"
+        loaded_parameters = {"parameter1": "value", "parameter2": "other value"}
+
+        self.assertTrue(NeuronLauncher.neuron_parameters_are_available_in_loaded_parameters(string_parameters,
+                                                                                            loaded_parameters))
+
+        # the string_parameters contains 2 parameters and one of them is not available in the dict
+        string_parameters = "this is a {{ parameter1 }} and this is {{ parameter2 }}"
+        loaded_parameters = {"parameter1": "value", "parameter3": "other value"}
+
+        self.assertFalse(NeuronLauncher.neuron_parameters_are_available_in_loaded_parameters(string_parameters,
+                                                                                             loaded_parameters))
+
+
+if __name__ == '__main__':
+    unittest.main()
 
+    # suite = unittest.TestSuite()
+    # suite.addTest(TestNeuronLauncher("test_start_neuron"))
+    # runner = unittest.TextTestRunner()
+    # runner.run(suite)

+ 79 - 31
kalliope/core/NeuronLauncher.py

@@ -1,5 +1,7 @@
 import logging
 
+import jinja2
+
 from kalliope.core.Utils.Utils import Utils
 from kalliope.core.ConfigurationManager.SettingLoader import SettingLoader
 
@@ -7,6 +9,10 @@ logging.basicConfig()
 logger = logging.getLogger("kalliope")
 
 
+class NeuronParameterNotAvailable(Exception):
+    pass
+
+
 class NeuronLauncher:
 
     def __init__(self):
@@ -41,36 +47,78 @@ class NeuronLauncher:
         :param parameters_dict: dict of parameter to load in each neuron if expecting a parameter
         :return: List of the instantiated neurons (no errors detected)
         """
-        instantiated_neuron = None
-        problem_in_neuron_found = False
-        if isinstance(neuron.parameters, dict):
-            # print neuron.parameters
-            if "args" in neuron.parameters:
-                logger.debug("The neuron waits for parameter")
-                # check that the user added parameters to his order
-                if parameters_dict is None:
-                    # we don't raise an error and break the program but we don't run the neuron
-                    problem_in_neuron_found = True
-                    Utils.print_danger("Error: The neuron %s is waiting for argument. "
-                                       "Argument found in bracket in the given order" % neuron.name)
+        if neuron.parameters is not None:
+            try:
+                neuron.parameters = cls._replace_brackets_by_loaded_parameter(neuron.parameters, parameters_dict)
+            except NeuronParameterNotAvailable:
+                Utils.print_danger("The neuron %s cannot be launched" % neuron.name)
+                return None
+        instantiated_neuron = NeuronLauncher.launch_neuron(neuron)
+        return instantiated_neuron
+
+    @classmethod
+    def _replace_brackets_by_loaded_parameter(cls, neuron_parameters, loaded_parameters):
+        """
+        Receive a value (which can be a str or dict or list) and instantiate value in double brace bracket
+        by the value specified in the loaded_parameters dict.
+        This method will call itself until all values has been instantiated
+        :param neuron_parameters: value to instantiate. Str or dict or list
+        :param loaded_parameters: dict of 
+        :return: 
+        """
+        if isinstance(neuron_parameters, str) or isinstance(neuron_parameters, unicode):
+            # replace bracket parameter only if the str contains brackets
+            if Utils.is_containing_bracket(neuron_parameters):
+                # check that the parameter to replace is available in the loaded_parameters dict
+                if cls.neuron_parameters_are_available_in_loaded_parameters(neuron_parameters, loaded_parameters):
+                    neuron_parameters = jinja2.Template(neuron_parameters).render(loaded_parameters)
+                    return str(neuron_parameters)
                 else:
-                    # we add wanted arguments the existing neuron parameter dict
-                    for arg in neuron.parameters["args"]:
-                        if arg in parameters_dict:
-                            logger.debug("Parameter %s added to the current parameter "
-                                         "of the neuron: %s" % (arg, neuron.name))
-                            neuron.parameters[arg] = parameters_dict[arg]
-                        else:
-                            # we don't raise an error and break the program but
-                            # we don't run the neuron
-                            problem_in_neuron_found = True
-                            Utils.print_danger("Error: Argument \"%s\" not found in the"
-                                               " order" % arg)
-
-            # if no error detected, we run the neuron
-            if not problem_in_neuron_found:
-                instantiated_neuron = cls.launch_neuron(neuron)
-            else:
-                Utils.print_danger("A problem has been found in the Synapse.")
+                    raise NeuronParameterNotAvailable
+            return neuron_parameters
 
-        return instantiated_neuron
+        if isinstance(neuron_parameters, dict):
+            returned_dict = dict()
+            for key, value in neuron_parameters.items():
+                returned_dict[key] = cls._replace_brackets_by_loaded_parameter(value, loaded_parameters)
+            return returned_dict
+
+        if isinstance(neuron_parameters, list):
+            returned_list = list()
+            for el in neuron_parameters:
+                templated_value = cls._replace_brackets_by_loaded_parameter(el, loaded_parameters)
+                returned_list.append(templated_value)
+            return returned_list
+        # in all other case (boolean or int for example) we return the value as it
+        return neuron_parameters
+
+    @classmethod
+    def neuron_parameters_are_available_in_loaded_parameters(cls, string_parameters, loaded_parameters):
+        """
+        Check that all parameters in brackets are available in the loaded_parameters dict
+        
+        E.g:
+        string_parameters = "this is a {{ parameter1 }}"
+        
+        Will return true if the loaded_parameters looks like the following
+        loaded_parameters { "parameter1": "a value"}        
+        
+        :param string_parameters: The string that contains one or more parameters in brace brackets
+        :param loaded_parameters: Dict of parameter
+        :return: True if all parameters in brackets have an existing key in loaded_parameters dict
+        """
+        list_parameters_with_brackets = Utils.find_all_matching_brackets(string_parameters)
+        # remove brackets to keep only the parameter name
+        list_parameters = list()
+        for parameter_with_brackets in list_parameters_with_brackets:
+            parameter = Utils.remove_spaces_in_brackets(parameter_with_brackets)
+            parameter = parameter.replace("{{", "").replace("}}", "")
+            list_parameters.append(parameter)
+
+        # check that the parameter name is available in the loaded_parameters dict
+        for parameters in list_parameters:
+            if loaded_parameters is None or parameters not in loaded_parameters:
+                Utils.print_danger("The parameter %s is not available in the order" % str(parameters))
+                return False
+
+        return True