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 parameters """ logger.debug("[NeuronLauncher] replacing brackets from %s, using %s" % (neuron_parameters, loaded_parameters)) # add variables from the short term memory to the list of loaded parameters that can be used in a template # the final dict is added into a key "intelora_memory" to not override existing keys loaded form the order memory_dict = dict() memory_dict["intelora_memory"] = Cortex.get_memory() if loaded_parameters is None: loaded_parameters = dict( ) # instantiate an empty dict in order to be able to add memory in it loaded_parameters.update(memory_dict) if isinstance(neuron_parameters, str) or isinstance( neuron_parameters, six.text_type): # 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): # add parameters from global variable into the final loaded parameter dict settings = cls.load_settings() loaded_parameters.update(settings.variables) neuron_parameters = jinja2.Template( neuron_parameters).render(loaded_parameters) neuron_parameters = Utils.encode_text_utf8( neuron_parameters) return str(neuron_parameters) else: raise NeuronParameterNotAvailable return neuron_parameters if isinstance(neuron_parameters, dict): returned_dict = dict() for key, value in neuron_parameters.items(): # following keys are reserved by intelora core if key in "say_template" or key in "file_template" or key in "intelora_memory" \ or key in "from_answer_link": returned_dict[key] = value else: 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
def test_remove_spaces_in_brackets(self): """ Test the Utils remove_spaces_in_brackets """ sentence = "This is the {{ bracket }}" expected_result = "This is the {{bracket}}" self.assertEqual(Utils.remove_spaces_in_brackets(sentence=sentence), expected_result, "Fail to remove spaces in one bracket") sentence = "This is the {{ bracket }} {{ second }}" expected_result = "This is the {{bracket}} {{second}}" self.assertEqual(Utils.remove_spaces_in_brackets(sentence=sentence), expected_result, "Fail to remove spaces in two brackets") # test with json sentence = "{\"params\": {\"apikey\": \"ISNOTMYPASSWORD\", " \ "\"query\": \"met le chauffage a {{ valeur }} degres\"}}" expected_result = "{\"params\": {\"apikey\": \"ISNOTMYPASSWORD\", " \ "\"query\": \"met le chauffage a {{valeur}} degres\"}}" self.assertEqual(Utils.remove_spaces_in_brackets(sentence=sentence), expected_result, "Fail to remove spaces in two brackets")
def start_neuron(cls, neuron, parameters_dict=None): """ Execute each neuron from the received neuron_list. Replace parameter if exist in the received dict of parameters_dict :param neuron: Neuron object to run :param parameters_dict: dict of parameter to load in each neuron if expecting a parameter :return: List of the instantiated neurons (no errors detected) """ if neuron.parameters is not None: try: neuron.parameters = cls._replace_brackets_by_loaded_parameter( neuron.parameters, parameters_dict) except NeuronParameterNotAvailable: Utils.print_danger( "Missing parameter in neuron %s. Execution skipped" % neuron.name) return None try: instantiated_neuron = NeuronLauncher.launch_neuron(neuron) except NeuronExceptions as e: Utils.print_danger("ERROR: Fail to execute neuron '%s'. " '%s' ". -> Execution skipped" % (neuron.name, e.message)) return None return instantiated_neuron
def _neuron_parameters_are_available_in_loaded_parameters( 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 for parameter_with_brackets in list_parameters_with_brackets: parameter = Utils.remove_spaces_in_brackets( parameter_with_brackets) parameter = parameter.replace("{{", "").replace("}}", "") if loaded_parameters is None or parameter not in loaded_parameters: Utils.print_danger( "The parameter %s is not available in the order" % str(parameter)) return False return True
def say(self, message): """ USe TTS to speak out loud the Message. A message can be a string, a list or a dict If it's a string, simply use the TTS with the message If it's a list, we select randomly a string in the list and give it to the TTS If it's a dict, we use the template given in parameter to create a string that we give to the TTS :param message: Can be a String or a dict or a list .. raises:: TTSModuleNotFound """ logger.debug("[NeuronModule] Say() called with message: %s" % message) tts_message = None # we can save parameters from the neuron in memory Cortex.save_neuron_parameter_in_memory(self.intelora_memory, message) if isinstance(message, str) or isinstance(message, six.text_type): logger.debug("[NeuronModule] message is string") tts_message = message if isinstance(message, list): logger.debug("[NeuronModule] message is list") tts_message = random.choice(message) if isinstance(message, dict): logger.debug("[NeuronModule] message is dict") tts_message = self._get_message_from_dict(message) if tts_message is not None: logger.debug("[NeuronModule] tts_message to say: %s" % tts_message) self.tts_message = tts_message Utils.print_success(tts_message) # process the audio only if the no_voice flag is false if self.no_voice: logger.debug( "[NeuronModule] no_voice is True, Intelora is muted") else: logger.debug( "[NeuronModule] no_voice is False, make Intelora speaking") HookManager.on_start_speaking() # get the instance of the TTS module tts_folder = None if self.settings.resources: tts_folder = self.settings.resources.tts_folder tts_module_instance = Utils.get_dynamic_class_instantiation( package_name="tts", module_name=self.tts.name, parameters=self.tts.parameters, resources_dir=tts_folder) # generate the audio file and play it tts_module_instance.say(tts_message) HookManager.on_stop_speaking()
def __init__(self, file_path=None): self.file_path = file_path if self.file_path is None: self.file_path = Utils.get_real_file_path(FILE_NAME) else: self.file_path = Utils.get_real_file_path(file_path) # if the returned file path is none, the file doesn't exist if self.file_path is None: raise SettingNotFound("Settings.yml file not found") self.yaml_config = self._get_yaml_config() self.settings = self._get_settings()
def test_find_all_matching_brackets(self): """ Test the Utils find all matching brackets """ sentence = "This is the {{bracket}}" expected_result = ["{{bracket}}"] self.assertEqual(Utils.find_all_matching_brackets(sentence=sentence), expected_result, "Fail to match one bracket") sentence = "This is the {{bracket}} {{second}}" expected_result = ["{{bracket}}", "{{second}}"] self.assertEqual(Utils.find_all_matching_brackets(sentence=sentence), expected_result, "Fail to match two brackets")
def test_get_next_value_list(self): # Success list_to_test = {1, 2, 3} self.assertEqual(Utils.get_next_value_list(list_to_test), 2, "Fail to match the expected next value from the list") # Failure list_to_test = {1} self.assertEqual(Utils.get_next_value_list(list_to_test), None, "Fail to ensure there is no next value from the list") # Behaviour list_to_test = {} self.assertEqual(Utils.get_next_value_list(list_to_test), None, "Fail to ensure the empty list return None value")
def save_parameter_from_order_in_memory(cls, order_parameters): """ Save key from the temp dict (where parameters loaded from the voice order where placed temporary) into the memory dict :param order_parameters: dict of key to save. {'key_name_in_memory': 'key_name_in_temp_dict'} :return True if a value has been saved in the intelora memory """ order_saved = False if order_parameters is not None: logger.debug( "[Cortex] save_parameter_from_order_in_memory - User want to save: %s" % order_parameters) logger.debug( "[Cortex] save_parameter_from_order_in_memory - Available parameters in orders: %s" % cls.temp) for key, value in order_parameters.items(): # ask the cortex to save in memory the target "key" if it was in the order if Utils.is_containing_bracket(value): # if the key exist in the temp dict we can load it with jinja value = jinja2.Template(value).render(Cortex.temp) if value: Cortex.save(key, value) order_saved = True return order_saved
def save_neuron_parameter_in_memory(cls, intelora_memory_dict, neuron_parameters): """ receive a dict of value send by the child neuron save in intelora memory all value E.g dict_parameter_to_save = {"my_key_to_save_in_memory": "{{ output_val_from_neuron }}"} neuron_parameter = {"output_val_from_neuron": "this_is_a_value" } then the cortex will save in memory the key "my_key_to_save_in_memory" and attach the value "this_is_a_value" :param neuron_parameters: dict of parameter the neuron has processed and send to the neurone module to be processed by the TTS engine :param intelora_memory_dict: a dict of key value the user want to save from the dict_neuron_parameter """ if intelora_memory_dict is not None: logger.debug("[Cortex] save_memory - User want to save: %s" % intelora_memory_dict) logger.debug( "[Cortex] save_memory - Available parameters in the neuron: %s" % neuron_parameters) for key, value in intelora_memory_dict.items(): # ask the cortex to save in memory the target "key" if it was in parameters of the neuron if isinstance(neuron_parameters, dict): if Utils.is_containing_bracket(value): value = jinja2.Template(value).render( neuron_parameters) Cortex.save(key, value)
def test_get_current_file_parent_parent_path(self): """ Expect to get back the parent parent path file """ path_to_test = "../intelora/core/Utils" expected_result = os.path.normpath("../intelora") self.assertEqual(Utils.get_current_file_parent_parent_path(path_to_test), expected_result, "fail getting the parent parent path from the given path")
def test_encode_text_utf8(self): """ Test encoding the text in utf8 """ sentence = "kâllìöpé" if sys.version_info[0] < 3: sentence = sentence.decode('utf8') expected_sentence = "kâllìöpé" self.assertEqual(Utils.encode_text_utf8(text=sentence), expected_sentence)
def _get_file_template(cls, file_template, message_dict): real_file_template_path = Utils.get_real_file_path(file_template) if real_file_template_path is None: raise TemplateFileNotFoundException( "Template file %s not found in templates folder" % real_file_template_path) # load the content of the file as template t = Template(cls._get_content_of_file(real_file_template_path)) returned_message = t.render(**message_dict) return returned_message
def serialize(self): """ This method allows to serialize in a proper way this object :return: A dict of name and parameters :rtype: Dict """ self.tts_message = Utils.encode_text_utf8(self.tts_message) return { 'neuron_name': self.neuron_name, 'generated_message': self.tts_message }
def test_get_dynamic_class_instantiation(self): """ Test that an instance as been instantiate properly. """ sl = SettingLoader() sl.settings.resource_dir = '/var/tmp/test/resources' neuron = Neuron(name='Say', parameters={'message': 'test dynamic class instantiate'}) self.assertTrue(isinstance(Utils.get_dynamic_class_instantiation(package_name="neurons", module_name=neuron.name.capitalize(), parameters=neuron.parameters, resources_dir='/var/tmp/test/resources'), Say), "Fail instantiate a class")
def launch_neuron(cls, neuron): """ Start a neuron plugin :param neuron: neuron object :type neuron: Neuron :return: """ logger.debug("Run neuron: \"%s\"" % (neuron.__str__())) settings = cls.load_settings() neuron_folder = None if settings.resources: neuron_folder = settings.resources.neuron_folder return Utils.get_dynamic_class_instantiation( package_name="neurons", module_name=neuron.name, parameters=neuron.parameters, resources_dir=neuron_folder)
def load_stt_plugin(self): if self.stt is None: self.stt_module_name = self.settings.default_stt_name logger.debug("[OrderListener] stt module name : %s" % self.stt_module_name) for stt_object in self.settings.stts: if stt_object.name == self.stt_module_name: stt_object.parameters["callback"] = self.callback # add the audio file path to the list of parameter if set if self.audio_file_path is not None: stt_object.parameters["audio_file_path"] = self.audio_file_path stt_folder = None if self.settings.resources: stt_folder = self.settings.resources.stt_folder return Utils.get_dynamic_class_instantiation(package_name='stt', module_name=stt_object.name.capitalize(), parameters=stt_object.parameters, resources_dir=stt_folder)
def test_is_containing_bracket(self): # Success order_to_test = "This test contains {{ bracket }}" self.assertTrue(Utils.is_containing_bracket(order_to_test), "Fail returning True when order contains spaced brackets") order_to_test = "This test contains {{bracket }}" self.assertTrue(Utils.is_containing_bracket(order_to_test), "Fail returning True when order contains right spaced bracket") order_to_test = "This test contains {{ bracket}}" self.assertTrue(Utils.is_containing_bracket(order_to_test), "Fail returning True when order contains left spaced bracket") order_to_test = "This test contains {{bracket}}" self.assertTrue(Utils.is_containing_bracket(order_to_test), "Fail returning True when order contains no spaced bracket") # Failure order_to_test = "This test does not contain bracket" self.assertFalse(Utils.is_containing_bracket(order_to_test), "Fail returning False when order has no brackets") # Behaviour order_to_test = "" self.assertFalse(Utils.is_containing_bracket(order_to_test), "Fail returning False when no order") # Behaviour int order_to_test = 6 self.assertFalse(Utils.is_containing_bracket(order_to_test), "Fail returning False when an int") # Behaviour unicode order_to_test = "j'aime les goûters l'été" self.assertFalse(Utils.is_containing_bracket(order_to_test), "Fail returning False when an int")
def _get_variables(settings): """ Return the dict of variables from the settings. :param settings: The YAML settings file :return: dict """ variables = dict() try: variables_files_name = settings["var_files"] # In case files are declared in settings.yml, make sure intelora can access them. for files in variables_files_name: var = Utils.get_real_file_path(files) if var is None: raise SettingInvalidException( "Variables file %s not found" % files) else: variables.update(YAMLLoader.get_config(var)) return variables except KeyError: # User does not provide this settings return dict()
def test_get_real_file_path(self): """ Expect to load the proper file following the order : - Provided absolute path - Current user path + file_name - /etc/intelora + file_name - /path/to/intelora/ +file_name """ ### # Test the absolute path dir_path = "/tmp/intelora/tests/" file_name = "test_real_file_path" absolute_path_to_test = os.path.join(dir_path, file_name) expected_result = absolute_path_to_test if not os.path.exists(dir_path): os.makedirs(dir_path) # touch the file open(absolute_path_to_test, 'a').close() self.assertEqual(Utils.get_real_file_path(absolute_path_to_test), expected_result, "Fail to match the given absolute path ") # Clean up if os.path.exists(absolute_path_to_test): os.remove(absolute_path_to_test) ### # test the Current path file_name = "test_real_file_path" expected_result = os.getcwd() + os.sep + file_name # touch the file open(file_name, 'a').close() self.assertEqual(Utils.get_real_file_path(file_name), expected_result, "Fail to match the Current path ") # Clean up if os.path.exists(file_name): os.remove(file_name) ### # test /etc/intelora # /!\ need permissions # dir_path = "/etc/intelora/" # file_name = "test_real_file_path" # path_to_test = os.path.join(dir_path,file_name) # expected_result = "/etc/intelora" + os.sep + file_name # if not os.path.exists(dir_path): # os.makedirs(dir_path) # # # touch the file # open(path_to_test, 'a').close() # # self.assertEquals(Utils.get_real_file_path(file_name), # expected_result, # "Fail to match the /etc/intelora path") # # Clean up # if os.path.exists(file_name): # os.remove(file_name) ### # /an/unknown/path/intelora/ dir_path = "../intelora/" file_name = "test_real_file_path" path_to_test = os.path.join(dir_path, file_name) expected_result = os.path.normpath(os.getcwd() + os.sep + os.pardir + os.sep + "intelora" + os.sep + file_name) if not os.path.exists(dir_path): os.makedirs(dir_path) # touch the file open(path_to_test, 'a').close() self.assertEqual(Utils.get_real_file_path(file_name), expected_result, "Fail to match the /an/unknown/path/intelora path") # Clean up if os.path.exists(expected_result): os.remove(expected_result)