def _generate_audio_file(self): """ Generic method used as a Callback in TTSModule """ # Prepare payload payload = self.get_payload() headers = {"Content-Type": "application/json", "Accept": "audio/wav"} url = "%s/synthesize?voice=%s" % (TTS_URL, self.voice) response = requests.post(url, auth=HTTPBasicAuth(self.username, self.password), headers=headers, json=payload) logger.debug("[Watson TTS] status code: %s" % response.status_code) if response.status_code == 200: # OK we get the audio we can write the sound file FileManager.write_in_file(self.file_path, response.content) Utils.print_info( "Text to Speech Engine: audio file generated by Watson") else: logger.debug("[Watson TTS] Fail to get audio. Header: %s" % response.headers)
def test_create_directory(self): """ Test to create a new directory. """ # set up cache_path = "/tmp/brain/tests/testDirectory" if os.path.exists(cache_path): os.removedirs(cache_path) # Test FileManager.create_directory FileManager.create_directory(cache_path) self.assertTrue(os.path.exists(cache_path), "Fail creating a directory to the path ") # Remove the directory os.removedirs(cache_path)
def _get_cache_path(settings): """ Return the path where to store the cache :param settings: The YAML settings file :type settings: dict :return: the path to store the cache :rtype: String :Example: cache_path = cls._get_cache_path(settings) .. seealso:: .. raises:: SettingNotFound, NullSettingException, SettingInvalidException .. warnings:: Class Method and Private """ try: cache_path = settings["cache_path"] except KeyError as e: raise SettingNotFound("%s setting not found" % e) if cache_path is None: raise NullSettingException("cache_path setting cannot be null") # test if that path is usable if FileManager.is_path_exists_or_creatable(cache_path): return cache_path else: raise SettingInvalidException( "The cache_path seems to be invalid: %s" % cache_path)
def convert_mp3_to_wav(file_path_mp3): """ PyAudio, AlsaPlayer, sounddevices do not support mp3 files MP3 files must be converted to a wave in order to be played This function assumes ffmpeg is available on the system :param file_path_mp3: the file path to convert from mp3 to wav """ logger.debug("[PlayerModule] Converting mp3 file to wav file: %s" % file_path_mp3) fnull = open(os.devnull, 'w') # temp file tmp_file_wav = file_path_mp3 + ".wav" # Convert mp3 to wave subprocess.call(['avconv', '-y', '-i', file_path_mp3, tmp_file_wav], stdout=fnull, stderr=fnull) # remove the original file FileManager.remove_file(file_path_mp3) # rename the temp file with the same name as the original file os.rename(tmp_file_wav, file_path_mp3)
def test_write_in_file(self): """ Test to write in file. """ # set up the context dir_path = "/tmp/brain/tests/" file_name = "test_FileManager_writeInFile" file_path = os.path.join(dir_path, file_name) in_file_text = "[Brain.ai] Testing the write_in_file method from Utils.FileManager" if os.path.exists(file_path): os.remove(file_path) if not os.path.exists(dir_path): os.makedirs(dir_path) # Test FileManager.write_in_file FileManager.write_in_file(file_path=file_path, content=in_file_text) with open(file_path, 'r') as content_file: content = content_file.read() self.assertEqual(content, in_file_text, "Fail writing in the file ") if sys.version_info[0] > 2: # Test writing of bytes object for python3 FileManager.write_in_file(file_path=file_path, content=bytes(in_file_text, 'utf-8')) with open(file_path, 'r') as content_file: content = content_file.read() self.assertEqual(content, in_file_text, "Fail writing in the file ") # Clean up if os.path.exists(file_path): os.remove(file_path) # run into IOError by trying to write something in root dir_path = "/root/" file_name = "test_FileManager_writeInFile" file_path = os.path.join(dir_path, file_name) self.assertFalse( FileManager.write_in_file(file_path=file_path, content=in_file_text))
def test_is_path_exists_or_creatable(self): """ Test the _is_path_exists_or_creatable 4 scenarii : - the file exists and is creatable : return True - the file does not exist but is creatable : return True - the file exists but is not allowed : return True --> need a review ! - the file does not exist and is not allowed : return False """ # set up the context dir_path = "/tmp/brain/tests/" file_name = "test_FileManager_fileIsPathExistsOrCreatable" file_path = os.path.join(dir_path, file_name) if os.path.exists(file_path): os.remove(file_path) if not os.path.exists(dir_path): os.makedirs(dir_path) # Test the file exist and creatable : return True with open(file_path, "wb") as file_open: file_open.write( b"[Brain.ai] Test Running the test_is_path_exists_or_creatable method" ) file_open.close() self.assertTrue(FileManager.is_path_exists_or_creatable(file_path), "Fail to assert the file exist ") # test the file not exist but creatable : return True os.remove(file_path) self.assertTrue(FileManager.is_path_exists_or_creatable(file_path), "Fail asserting the file does not exist ") # test the file exist but not creatable : return True # file_exist_not_allowed = "/root/.ssh/known_hosts" # self.assertTrue(FileManager.is_path_creatable(file_exist_not_allowed)) # test the file not exist and not allowed : return False not_allowed_root_path = "/root/" not_allowed_path = os.path.join(not_allowed_root_path, file_name) self.assertFalse(FileManager.is_path_creatable(not_allowed_path), "Fail to assert not accessing this path ")
def test_remove_file(self): """ Test to remove a file """ # set up the context dir_path = "/tmp/brain/tests/" file_name = "test_FileManager_fileRemove" file_path = os.path.join(dir_path, file_name) if os.path.exists(file_path): os.remove(file_path) if not os.path.exists(dir_path): os.makedirs(dir_path) # Test to remove the file # FileManager.remove_file with open(file_path, "wb") as file_open: file_open.write(b"") file_open.close() FileManager.remove_file(file_path=file_path) self.assertFalse(os.path.exists(file_path), "Fail removing the file")
def test_is_file_already_in_cache(self): """ Test if file is already stored in cache """ base_cache_path = "/tmp/brain/tests/TTSModule/tests/default/" md5_word = "5c186d1e123be2667fb5fd54640e4fd0" file_path = os.path.join(base_cache_path, "5c186d1e123be2667fb5fd54640e4fd0.tts") if os.path.isfile(file_path): # Remove the file FileManager.remove_file(file_path) # Create a tmp file if not os.path.exists(base_cache_path): os.makedirs(base_cache_path) tmp_path = os.path.join(base_cache_path, md5_word + ".tts") FileManager.write_in_file( tmp_path, "[brain-test] test_is_file_already_in_cache") # Test true self.assertTrue( TTSModule._is_file_already_in_cache( base_cache_path=base_cache_path, file_path=file_path), "Fail retrieving the cached file. The file does not exist but it should !" ) # Remove the tmp file FileManager.remove_file(tmp_path) # Test False self.assertFalse( TTSModule._is_file_already_in_cache( base_cache_path=base_cache_path, file_path=file_path), "Fail asserting that the file does not exist.")
def test_is_path_creatable(self): """ Test if the path is creatable for the user Does the user has the permission to use this path ? """ # set up the context dir_path = "/tmp/brain/tests/" file_name = "test_FileManager_filePathCreatable" file_path = os.path.join(dir_path, file_name) if os.path.exists(file_path): os.remove(file_path) if not os.path.exists(dir_path): os.makedirs(dir_path) # test not allowed : return False not_allowed_root_path = "/root/" not_allowed_path = os.path.join(not_allowed_root_path, file_name) self.assertFalse(FileManager.is_path_creatable(not_allowed_path), "Fail to assert not accessing this path ") # test allowed : return True self.assertTrue(FileManager.is_path_creatable(file_path))
def test_generate_and_play(self): """ Test to generate and play sound """ def new_play_audio(TTSModule): pass words = "brain" with mock.patch.object(TTSModule, 'play_audio', new=new_play_audio): settings = Settings(cache_path="/tmp/brain/tests") self.TTSMod.settings = settings # test missing callback with self.assertRaises(TtsGenerateAudioFunctionNotFound): self.TTSMod.generate_and_play(words=words) # Assert Callback is called # no Cache self.TTSMod.cache = False generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child= generate_audio_function_from_child) generate_audio_function_from_child.assert_called() # with cache True but not existing on system self.TTSMod.cache = True generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child= generate_audio_function_from_child) generate_audio_function_from_child.assert_called() # with cache True and existing on system # create tmp file tmp_base_path = "/tmp/brain/tests/TTSModule/tests/default/" file_path = os.path.join(tmp_base_path, "5c186d1e123be2667fb5fd54640e4fd0.tts") if os.path.isfile(file_path): # Remove the file FileManager.remove_file(file_path) if not os.path.exists(tmp_base_path): os.makedirs(tmp_base_path) FileManager.write_in_file(file_path, "[brain-test] test_generate_and_play") self.TTSMod.cache = True generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child= generate_audio_function_from_child) generate_audio_function_from_child.assert_not_called() # Remove the tmp file FileManager.remove_file(file_path)
def test_file_is_empty(self): """ Test that the file is empty """ # set up the context dir_path = "/tmp/brain/tests/" file_name = "test_FileManager_fileIsEmpty" file_path = os.path.join(dir_path, file_name) if os.path.exists(file_path): os.remove(file_path) if not os.path.exists(dir_path): os.makedirs(dir_path) # Test FileManager.file_is_empty with open(file_path, "wb") as file_open: file_open.write(b"") file_open.close() self.assertTrue(FileManager.file_is_empty(file_path=file_path), "Fail matching to verify that file is empty ") # Clean up if os.path.exists(file_path): os.remove(file_path)
def create_file_manager(self): file_manager = FileManager() self.assertIsInstance(FileManager, file_manager)
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) # Add routing rules self.app.add_url_rule('/', view_func=self.get_main_page, methods=['GET']) # Synapses 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']) # Life Cycle self.app.add_url_rule('/shutdown/', view_func=self.shutdown_server, methods=['POST']) # Settings self.app.add_url_rule('/settings', view_func=self.get_current_settings, methods=['GET']) self.app.add_url_rule('/settings/deaf/', view_func=self.get_deaf, methods=['GET']) self.app.add_url_rule('/settings/deaf/', view_func=self.set_deaf, methods=['POST']) self.app.add_url_rule('/settings/mute/', view_func=self.get_mute, methods=['GET']) self.app.add_url_rule('/settings/mute/', view_func=self.set_mute, methods=['POST']) self.app.add_url_rule('/settings/ambient_noise_second/', view_func=self.get_ambient_noise_second, methods=['GET']) self.app.add_url_rule( '/settings/ambient_noise_second/', view_func=self.set_adjust_for_ambient_noise_second, methods=['POST']) self.app.add_url_rule('/settings/energy_threshold/', view_func=self.get_energy_threshold, methods=['GET']) self.app.add_url_rule('/settings/energy_threshold/', view_func=self.set_energy_threshold, methods=['POST']) self.app.add_url_rule('/settings/default_tts/', view_func=self.get_default_tts, methods=['GET']) self.app.add_url_rule('/settings/default_tts/', view_func=self.set_default_tts, methods=['POST']) self.app.add_url_rule('/settings/default_stt/', view_func=self.get_default_stt, methods=['GET']) self.app.add_url_rule('/settings/default_stt/', view_func=self.set_default_stt, methods=['POST']) self.app.add_url_rule('/settings/default_player/', view_func=self.get_default_player, methods=['GET']) self.app.add_url_rule('/settings/default_player/', view_func=self.set_default_player, methods=['POST']) self.app.add_url_rule('/settings/default_trigger/', view_func=self.get_default_trigger, methods=['GET']) self.app.add_url_rule('/settings/default_trigger/', view_func=self.set_default_trigger, methods=['POST']) self.app.add_url_rule('/settings/hooks/', view_func=self.get_hooks, methods=['GET']) self.app.add_url_rule('/settings/hooks/', view_func=self.set_hooks, methods=['POST']) self.app.add_url_rule('/settings/variables/', view_func=self.get_variables, methods=['GET']) self.app.add_url_rule('/settings/variables/', view_func=self.set_variables, methods=['POST'])