def test_get_rest_api(self): expected_rest_api = RestAPI(password_protected=True, active=True, login="******", password="******", port=5000, allowed_cors_origin=False) sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(expected_rest_api, sl._get_rest_api(self.settings_dict))
def test_get_players(self): player1 = Player(name="mplayer", parameters={}) player2 = Player(name="pyalsaaudio", parameters={'device': 'default'}) sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual([player1, player2], sl._get_players(self.settings_dict))
def test_get_start_options(self): expected_result = { "muted": True } sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(expected_result, sl._get_start_options(self.settings_dict))
def test_get_resources(self): resources = Resources(neuron_folder="/tmp/intelora/tests/intelora_resources_dir/neurons", stt_folder="/tmp/intelora/tests/intelora_resources_dir/stt", tts_folder="/tmp/intelora/tests/intelora_resources_dir/tts", trigger_folder="/tmp/intelora/tests/intelora_resources_dir/trigger") expected_resource = resources sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(expected_resource, sl._get_resources(self.settings_dict))
def test_get_variables(self): expected_result = { "author": "Lamonf", "test_number": 60, "test": "intelora" } sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(expected_result, sl._get_variables(self.settings_dict))
def create_app(self): """ executed once at the beginning of the test """ # be sure that the singleton haven't been loaded before Singleton._instances = {} current_path = os.getcwd() if "/tests" in os.getcwd(): full_path_brain_to_test = current_path + os.sep + "brains/brain_test_api.yml" self.audio_file = "files/bonjour.wav" else: full_path_brain_to_test = current_path + os.sep + "tests/brains/brain_test_api.yml" self.audio_file = "tests/files/bonjour.wav" # rest api config sl = SettingLoader() sl.settings.rest_api.password_protected = False sl.settings.active = True sl.settings.port = 5000 sl.settings.allowed_cors_origin = "*" sl.settings.default_synapse = None sl.settings.hooks["on_order_not_found"] = "order-not-found-synapse" # prepare a test brain brain_to_test = full_path_brain_to_test brain_loader = BrainLoader(file_path=brain_to_test) brain = brain_loader.brain self.app = Flask(__name__) self.app.config['TESTING'] = True self.flask_api = FlaskAPI(self.app, port=5000, brain=brain) self.client = self.app.test_client() return self.flask_api.app
def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ sl = SettingLoader() settings = sl.settings return username == settings.rest_api.login and password == settings.rest_api.password
def __init__(self, **kwargs): # set parameter from what we receive from the settings self.cache = kwargs.get('cache', False) self.language = kwargs.get('language', "default") self.voice = kwargs.get('voice', "default") # the name of the TSS is the name of the Tss module that have instantiated TTSModule self.tts_caller_name = self.__class__.__name__ # we don't know yet the words that will be converted to an audio and so we don't have the audio path yet too self.words = None self.file_path = None self.base_cache_path = None # load settings sl = SettingLoader() self.settings = sl.settings self.player = PlayerLauncher.get_player(settings=self.settings) # create the path in the tmp folder base_path = os.path.join(self.settings.cache_path, self.tts_caller_name, self.language, self.voice) FileManager.create_directory(base_path) logger.debug( "Class TTSModule called from module %s, cache: %s, language: %s, voice: %s" % (self.tts_caller_name, self.cache, self.language, self.voice))
def decorated(*args, **kwargs): sl = SettingLoader() settings = sl.settings if settings.rest_api.password_protected: auth = request.authorization if not auth or not check_auth(auth.username, auth.password): return authenticate() return f(*args, **kwargs)
def test_get_hooks(self): # test with only one hook set settings = dict() settings["hooks"] = { "on_start": "test_synapse" } expected_dict = { "on_start": "test_synapse", "on_waiting_for_trigger": None, "on_triggered": None, "on_start_listening": None, "on_stop_listening": None, "on_order_found": None, "on_order_not_found": None, "on_mute": None, "on_unmute": None, "on_start_speaking": None, "on_stop_speaking": None } returned_dict = SettingLoader._get_hooks(settings) self.assertEqual(returned_dict, expected_dict) # test with no hook set settings = dict() expected_dict = { "on_start": None, "on_waiting_for_trigger": None, "on_triggered": None, "on_start_listening": None, "on_stop_listening": None, "on_order_found": None, "on_order_not_found": None, "on_mute": None, "on_unmute": None, "on_start_speaking": None, "on_stop_speaking": None } returned_dict = SettingLoader._get_hooks(settings) self.assertEqual(returned_dict, expected_dict)
def test_get_settings(self): settings_object = Settings() settings_object.default_tts_name = "pico2wave" settings_object.default_stt_name = "google" settings_object.default_trigger_name = "snowboy" settings_object.default_player_name = "mplayer" tts1 = Tts(name="pico2wave", parameters={'cache': True, 'language': 'fr-FR'}) tts2 = Tts(name="voxygen", parameters={'voice': 'Agnes', 'cache': True}) settings_object.ttss = [tts1, tts2] stt = Stt(name="google", parameters={'language': 'fr-FR'}) settings_object.stts = [stt] trigger1 = Trigger(name="snowboy", parameters={'pmdl_file': 'trigger/snowboy/resources/intelora-FR-6samples.pmdl'}) settings_object.triggers = [trigger1] player1 = Player(name="mplayer", parameters={}) player2 = Player(name="pyalsaaudio", parameters={"device": "default"}) settings_object.players = [player1, player2] settings_object.rest_api = RestAPI(password_protected=True, active=True, login="******", password="******", port=5000, allowed_cors_origin=False) settings_object.cache_path = '/tmp/intelora_tts_cache' resources = Resources(neuron_folder="/tmp/intelora/tests/intelora_resources_dir/neurons", stt_folder="/tmp/intelora/tests/intelora_resources_dir/stt", tts_folder="/tmp/intelora/tests/intelora_resources_dir/tts", trigger_folder="/tmp/intelora/tests/intelora_resources_dir/trigger") settings_object.resources = resources settings_object.variables = { "author": "Lamonf", "test_number": 60, "test": "intelora" } settings_object.start_options = { "muted": True } settings_object.machine = platform.machine() settings_object.recognition_options = RecognitionOptions() settings_object.hooks = {'on_waiting_for_trigger': 'test', 'on_stop_listening': None, 'on_start_listening': None, 'on_order_found': None, 'on_start': ['on-start-synapse', 'bring-led-on'], 'on_unmute': [], 'on_triggered': ['on-triggered-synapse'], 'on_mute': [], 'on_order_not_found': [ 'order-not-found-synapse'], 'on_start_speaking': None, 'on_stop_speaking': None, } sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(settings_object, sl.settings)
def __init__(self, **kwargs): """ Class used by neuron for talking :param kwargs: Same parameter as the Child. Can contain info about the tts to use instead of the default one """ # get the child who called the class child_name = self.__class__.__name__ self.neuron_name = child_name sl = SettingLoader() self.settings = sl.settings brain_loader = BrainLoader() self.brain = brain_loader.brain # a dict of overridden TTS parameters if provided by the user self.override_tts_parameters = kwargs.get('tts', None) # create the TTS instance self.tts = None if self.override_tts_parameters is None or not isinstance( self.override_tts_parameters, dict): # we get the default TTS self.tts = self._get_tts_object(settings=self.settings) else: for key, value in self.override_tts_parameters.items(): tts_name = key tts_parameters = value self.tts = self._get_tts_object( tts_name=tts_name, override_parameter=tts_parameters, settings=self.settings) # get templates if provided # Check if there is a template associate to the output message self.say_template = kwargs.get('say_template', None) # check if there is a template file associate to the output message self.file_template = kwargs.get('file_template', None) # keep the generated message self.tts_message = None # if the current call is api one self.is_api_call = kwargs.get('is_api_call', False) # if the current call want to mute intelora self.no_voice = kwargs.get('no_voice', False) # boolean to know id the synapse is waiting for an answer self.is_waiting_for_answer = False # the synapse name to add the the buffer self.pending_synapse = None # a dict of parameters the user ask to save in short term memory self.intelora_memory = kwargs.get('intelora_memory', None) # parameters loaded from the order can be save now Cortex.save_parameter_from_order_in_memory(self.intelora_memory)
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 __init__(self, file_path=None): sl = SettingLoader() self.settings = sl.settings self.file_path = file_path if self.file_path is None: # we don't provide a file path, so search for the default one 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 BrainNotFound("brain file not found") self.yaml_config = self.get_yaml_config() self.brain = self.load_brain()
def setUp(self): # Init the folders, otherwise it raises an exceptions os.makedirs("/tmp/intelora/tests/intelora_resources_dir/neurons") os.makedirs("/tmp/intelora/tests/intelora_resources_dir/stt") os.makedirs("/tmp/intelora/tests/intelora_resources_dir/tts") os.makedirs("/tmp/intelora/tests/intelora_resources_dir/trigger") # get current script directory path. We are in /an/unknown/path/intelora/core/tests cur_script_directory = os.path.dirname( os.path.abspath(inspect.getfile(inspect.currentframe()))) # get parent dir. Now we are in /an/unknown/path/intelora root_dir = os.path.normpath(cur_script_directory + os.sep + os.pardir) self.settings_file_to_test = root_dir + os.sep + "tests/settings/settings_test.yml" self.settings = SettingLoader(file_path=self.settings_file_to_test)
def __init__(self, app, port=5000, brain=None, allowed_cors_origin=False): """ :param app: Flask API :param port: Port to listen :param brain: Brain object :type brain: Brain """ super(FlaskAPI, self).__init__() self.app = app self.port = port self.brain = brain self.allowed_cors_origin = allowed_cors_origin # get current settings sl = SettingLoader() self.settings = sl.settings # api_response sent by the Order Analyser when using the /synapses/start/audio URL self.api_response = None # boolean used to notify the main process that we get the list of returned synapse self.order_analyser_return = False # configure the upload folder app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # create the temp folder FileManager.create_directory(UPLOAD_FOLDER) # Flask configuration remove default Flask behaviour to encode to ASCII self.app.url_map.strict_slashes = False self.app.config['JSON_AS_ASCII'] = False if self.allowed_cors_origin is not False: CORS(app, resources={r"/*": {"origins": allowed_cors_origin}}, supports_credentials=True) # no voice flag self.no_voice = False # Add routing rules self.app.add_url_rule('/', view_func=self.get_main_page, methods=['GET']) self.app.add_url_rule('/synapses', view_func=self.get_synapses, methods=['GET']) self.app.add_url_rule('/synapses/<synapse_name>', view_func=self.get_synapse, methods=['GET']) self.app.add_url_rule('/synapses/start/id/<synapse_name>', view_func=self.run_synapse_by_name, methods=['POST']) self.app.add_url_rule('/synapses/start/order', view_func=self.run_synapse_by_order, methods=['POST']) self.app.add_url_rule('/synapses/start/audio', view_func=self.run_synapse_by_audio, methods=['POST']) self.app.add_url_rule('/shutdown/', view_func=self.shutdown_server, methods=['POST']) self.app.add_url_rule('/mute/', view_func=self.get_mute, methods=['GET']) self.app.add_url_rule('/mute/', view_func=self.set_mute, methods=['POST'])
def __init__(self): super(Order, self).__init__() Utils.print_info('Starting order signal') # load settings and brain from singleton sl = SettingLoader() self.settings = sl.settings self.brain = BrainLoader().brain # keep in memory the order to process self.order_to_process = None # get the player instance self.player_instance = PlayerLauncher.get_player(settings=self.settings) # save an instance of the trigger self.trigger_instance = None self.trigger_callback_called = False self.is_trigger_muted = False # If intelora is asked to start muted if self.settings.start_options['muted'] is True: self.is_trigger_muted = True # save the current order listener self.order_listener = None self.order_listener_callback_called = False # Initialize the state machine self.machine = Machine(model=self, states=Order.states, initial='init', queued=True) # define transitions self.machine.add_transition('start_trigger', ['init', 'analysing_order'], 'starting_trigger') self.machine.add_transition('wait_trigger_callback', 'starting_trigger', 'waiting_for_trigger_callback') self.machine.add_transition('stop_trigger', 'waiting_for_trigger_callback', 'stopping_trigger') self.machine.add_transition('wait_for_order', 'stopping_trigger', 'waiting_for_order_listener_callback') self.machine.add_transition('analyse_order', 'waiting_for_order_listener_callback', 'analysing_order') self.machine.add_ordered_transitions() # add method which are called when changing state self.machine.on_enter_starting_trigger('start_trigger_process') self.machine.on_enter_waiting_for_trigger_callback('waiting_for_trigger_callback_thread') self.machine.on_enter_stopping_trigger('stop_trigger_process') self.machine.on_enter_start_order_listener('start_order_listener_thread') self.machine.on_enter_waiting_for_order_listener_callback('waiting_for_order_listener_callback_thread') self.machine.on_enter_analysing_order('analysing_order_thread')
def test_launch_neuron(self): """ Test the Neuron Launcher trying to start a Neuron """ neuron = Neuron(name='neurone1', parameters={'var1': 'val1'}) sl = SettingLoader() resources = Resources(neuron_folder='/var/tmp/test/resources') sl.settings.resources = resources with mock.patch("intelora.core.Utils.get_dynamic_class_instantiation" ) as mock_get_class_instantiation: NeuronLauncher.launch_neuron(neuron=neuron) mock_get_class_instantiation.assert_called_once_with( package_name="neurons", module_name=neuron.name, parameters=neuron.parameters, resources_dir=sl.settings.resources.neuron_folder) mock_get_class_instantiation.reset_mock()
def __init__(self, **kwargs): """ This class is used to manage community resources. :param kwargs: git-url: the url of the module to clone and install """ super(ResourcesManager, self).__init__() # get settings sl = SettingLoader() self.settings = sl.settings # in case of update or install, url where self.git_url = kwargs.get('git_url', None) # temp path where we install the new module self.tmp_path = tempfile.gettempdir( ) + "/intelora/resources/" + TMP_GIT_FOLDER self.dna_file_path = self.tmp_path + os.sep + DNA_FILE_NAME self.install_file_path = self.tmp_path + os.sep + INSTALL_FILE_NAME self.dna = None
def __init__(self, brain=None): """ Load a GUI in a shell console for testing TTS, STT and brain configuration :param brain: The Brain object provided by the brain.yml :type brain: Brain .. seealso:: Brain """ # override brain self.brain = brain # get settings sl = SettingLoader() self.settings = sl.settings locale.setlocale(locale.LC_ALL, '') self.d = Dialog(dialog="dialog") self.d.set_background_title("Intelora Shell UI") self.show_main_menu()
def execute_synapses_in_hook_name(cls, hook_name): # need to import SynapseLauncher from here to avoid cross import from intelora.core.SynapseLauncher import SynapseLauncher logger.debug("[HookManager] calling synapses in hook name: %s" % hook_name) settings = SettingLoader().settings # list of synapse to execute list_synapse = settings.hooks[hook_name] logger.debug("[HookManager] hook: %s , type: %s" % (hook_name, type(list_synapse))) if isinstance(list_synapse, list): return SynapseLauncher.start_synapse_by_list_name(list_synapse, new_lifo=True) if isinstance(list_synapse, str): return SynapseLauncher.start_synapse_by_name(list_synapse, new_lifo=True) return None
def __init__(self, callback=None, stt=None, audio_file_path=None): """ This class is called after we catch the hotword that has woken up Intelora. We now wait for an order spoken out loud by the user, translate the order into a text and run the action attached to this order from settings :param callback: callback function to call :type callback: Callback function :param stt: Speech to text plugin name to load. If not provided, :type stt: STT instance we will load the default one set in settings .. seealso:: STT """ # this is a trick to ignore ALSA output error # see http://stackoverflow.com/questions/7088672/pyaudio-working-but-spits-out-error-messages-each-time super(OrderListener, self).__init__() self.stt = stt self._ignore_stderr() self.stt_module_name = stt self.callback = callback sl = SettingLoader() self.settings = sl.settings self.stt_instance = None self.audio_file_path = audio_file_path
def test_get_ttss(self): tts1 = Tts(name="pico2wave", parameters={'cache': True, 'language': 'fr-FR'}) tts2 = Tts(name="voxygen", parameters={'voice': 'Agnes', 'cache': True}) sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual([tts1, tts2], sl._get_ttss(self.settings_dict))
def test_get_default_trigger(self): expected_default_trigger = "snowboy" sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(expected_default_trigger, sl._get_default_trigger(self.settings_dict))
def test_get_stts(self): stt = Stt(name="google", parameters={'language': 'fr-FR'}) sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual([stt], sl._get_stts(self.settings_dict))
def test_get_yaml_config(self): sl = SettingLoader(file_path=self.settings_file_to_test) self.maxDiff = None self.assertDictEqual(sl.yaml_config, self.settings_dict)
def test_singleton(self): s1 = SettingLoader(file_path=self.settings_file_to_test) s2 = SettingLoader(file_path=self.settings_file_to_test) self.assertTrue(s1.settings is s2.settings)
def test_get_cache_path(self): expected_cache_path = '/tmp/intelora_tts_cache' sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual(expected_cache_path, sl._get_cache_path(self.settings_dict))
def main(): """Entry point of Intelora program.""" # parse argument. the script name is removed try: parser = parse_args(sys.argv[1:]) except SystemExit: sys.exit(1) # check if we want debug configure_logging(debug=parser.debug) logger.debug("intelora args: %s" % parser) # by default, no brain file is set. # Use the default one: brain.yml in the root path brain_file = None # check if user set a brain.yml file if parser.brain_file: brain_file = parser.brain_file # check the user provide a valid action if parser.action not in ACTION_LIST: Utils.print_warning("%s is not a recognised action\n" % parser.action) sys.exit(1) # install modules if parser.action == "install": if not parser.git_url: Utils.print_danger("You must specify the git url") sys.exit(1) else: parameters = {"git_url": parser.git_url} res_manager = ResourcesManager(**parameters) res_manager.install() return # uninstall modules if parser.action == "uninstall": if not parser.neuron_name \ and not parser.stt_name \ and not parser.tts_name \ and not parser.trigger_name\ and not parser.signal_name: Utils.print_danger("You must specify a module name with " "--neuron-name " "or --stt-name " "or --tts-name " "or --trigger-name " "or --signal-name") sys.exit(1) else: res_manager = ResourcesManager() res_manager.uninstall(neuron_name=parser.neuron_name, stt_name=parser.stt_name, tts_name=parser.tts_name, trigger_name=parser.trigger_name, signal_name=parser.signal_name) return # load the brain once brain_loader = BrainLoader(file_path=brain_file) brain = brain_loader.brain # load settings # get global configuration once settings_loader = SettingLoader() settings = settings_loader.settings if parser.action == "start": # user set a synapse to start if parser.run_synapse is not None: SynapseLauncher.start_synapse_by_name(parser.run_synapse, brain=brain) if parser.run_order is not None: SynapseLauncher.run_matching_synapse_from_order(parser.run_order, brain=brain, settings=settings, is_api_call=False) if (parser.run_synapse is None) and (parser.run_order is None): # if --muted if parser.muted: settings.start_options['muted'] = True # start rest api start_rest_api(settings, brain) start_intelora(settings, brain) if parser.action == "gui": try: ShellGui(brain=brain) except (KeyboardInterrupt, SystemExit): Utils.print_info("Intelora stopped") sys.exit(0)
def test_get_triggers(self): trigger1 = Trigger(name="snowboy", parameters={'pmdl_file': 'trigger/snowboy/resources/intelora-FR-6samples.pmdl'}) sl = SettingLoader(file_path=self.settings_file_to_test) self.assertEqual([trigger1], sl._get_triggers(self.settings_dict))